diff --git a/src/DurableTask.AzureStorage/OrchestrationSessionManager.cs b/src/DurableTask.AzureStorage/OrchestrationSessionManager.cs index b69593c80..c64cad0e6 100644 --- a/src/DurableTask.AzureStorage/OrchestrationSessionManager.cs +++ b/src/DurableTask.AzureStorage/OrchestrationSessionManager.cs @@ -277,7 +277,7 @@ async Task> DedupeExecutionStartedMessagesAsync( // "Remote" -> the instance ID info comes from the Instances table that we're querying IAsyncEnumerable instances = this.trackingStore.FetchInstanceStatusAsync(instanceIds, cancellationToken); IDictionary remoteOrchestrationsById = - await instances.ToDictionaryAsync(o => o.State.OrchestrationInstance.InstanceId, comparer: null, cancellationToken); + await instances.ToDictionaryAsync(o => o.State.OrchestrationInstance.InstanceId, comparer: StringComparer.OrdinalIgnoreCase, cancellationToken); foreach (MessageData message in executionStartedMessages) { diff --git a/test/DurableTask.AzureStorage.Tests/AzureStorageScaleTests.cs b/test/DurableTask.AzureStorage.Tests/AzureStorageScaleTests.cs index 7c6b9a4e0..cc6f338bb 100644 --- a/test/DurableTask.AzureStorage.Tests/AzureStorageScaleTests.cs +++ b/test/DurableTask.AzureStorage.Tests/AzureStorageScaleTests.cs @@ -210,7 +210,7 @@ private async Task EnsureLeasesMatchControlQueue(string directoryReference, Blob /// REQUIREMENT: Workers can be added or removed at any time and control-queue partitions are load-balanced automatically. /// REQUIREMENT: No two workers will ever process the same control queue. /// - [TestMethod] + [DataTestMethod] [DataRow(PartitionManagerType.V1Legacy, 30)] [DataRow(PartitionManagerType.V2Safe, 180)] public async Task MultiWorkerLeaseMovement(PartitionManagerType partitionManagerType, int timeoutInSeconds) diff --git a/test/DurableTask.AzureStorage.Tests/AzureStorageScenarioTests.cs b/test/DurableTask.AzureStorage.Tests/AzureStorageScenarioTests.cs index 1ecd5056f..93d0ffca2 100644 --- a/test/DurableTask.AzureStorage.Tests/AzureStorageScenarioTests.cs +++ b/test/DurableTask.AzureStorage.Tests/AzureStorageScenarioTests.cs @@ -50,7 +50,7 @@ public class AzureStorageScenarioTests /// /// End-to-end test which validates a simple orchestrator function which doesn't call any activity functions. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task HelloWorldOrchestration_Inline(bool enableExtendedSessions) @@ -73,7 +73,7 @@ public async Task HelloWorldOrchestration_Inline(bool enableExtendedSessions) /// /// End-to-end test which runs a simple orchestrator function that calls a single activity function. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task HelloWorldOrchestration_Activity(bool enableExtendedSessions) @@ -157,7 +157,7 @@ public async Task ParentOfSequentialOrchestration() /// /// End-to-end test which runs a slow orchestrator that causes work item renewal /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LongRunningOrchestrator(bool enableExtendedSessions) @@ -266,7 +266,7 @@ public async Task NoInstancesGetAllOrchestrationStatusesNullContinuationToken() } } - [TestMethod] + [DataTestMethod] [DataRow(false, false)] [DataRow(true, false)] [DataRow(false, true)] @@ -287,7 +287,7 @@ public async Task EventConversation(bool enableExtendedSessions, bool useFireAnd } } - [TestMethod] + [DataTestMethod] [DataRow(false)] [DataRow(true)] public async Task AutoStart(bool enableExtendedSessions) @@ -308,7 +308,7 @@ public async Task AutoStart(bool enableExtendedSessions) } } - [TestMethod] + [DataTestMethod] [DataRow(false)] [DataRow(true)] public async Task ContinueAsNewThenTimer(bool enableExtendedSessions) @@ -640,7 +640,7 @@ public async Task PurgeInstanceHistoryForTimePeriodDeletePartially() /// End-to-end test which validates parallel function execution by enumerating all files in the current directory /// in parallel and getting the sum total of all file sizes. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task ParallelOrchestration(bool enableExtendedSessions) @@ -660,7 +660,7 @@ public async Task ParallelOrchestration(bool enableExtendedSessions) } } - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeFanOutOrchestration(bool enableExtendedSessions) @@ -699,7 +699,7 @@ public async Task FanOutOrchestration_LargeHistoryBatches() /// /// End-to-end test which validates the ContinueAsNew functionality by implementing a counter actor pattern. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task ActorOrchestration(bool enableExtendedSessions) @@ -747,7 +747,7 @@ public async Task ActorOrchestration(bool enableExtendedSessions) /// /// End-to-end test which validates the ContinueAsNew functionality by implementing character counter actor pattern. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task ActorOrchestrationForLargeInput(bool enableExtendedSessions) @@ -758,7 +758,7 @@ public async Task ActorOrchestrationForLargeInput(bool enableExtendedSessions) /// /// End-to-end test which validates the deletion of all data generated by the ContinueAsNew functionality in the character counter actor pattern. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task ActorOrchestrationDeleteAllLargeMessageBlobs(bool enableExtendedSessions) @@ -872,7 +872,7 @@ private async Task> ValidateCharacterCoun /// /// End-to-end test which validates the Terminate functionality. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task TerminateOrchestration(bool enableExtendedSessions) @@ -902,7 +902,7 @@ public async Task TerminateOrchestration(bool enableExtendedSessions) /// /// End-to-end test which validates the Suspend-Resume functionality. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task SuspendResumeOrchestration(bool enableExtendedSessions) @@ -941,7 +941,7 @@ public async Task SuspendResumeOrchestration(bool enableExtendedSessions) /// /// Test that a suspended orchestration can be terminated. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task TerminateSuspendedOrchestration(bool enableExtendedSessions) @@ -970,7 +970,7 @@ public async Task TerminateSuspendedOrchestration(bool enableExtendedSessions) /// Test that a pending orchestration can be terminated (including tests with a large termination reason that will need to be /// stored in blob storage). /// - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -1277,7 +1277,7 @@ public async Task RewindNestedSubOrchestrationTest() } } - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task TimerCancellation(bool enableExtendedSessions) @@ -1305,7 +1305,7 @@ public async Task TimerCancellation(bool enableExtendedSessions) /// /// End-to-end test which validates the handling of durable timer expiration. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task TimerExpiration(bool enableExtendedSessions) @@ -1331,7 +1331,7 @@ public async Task TimerExpiration(bool enableExtendedSessions) } } - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task TimerDelay(bool useUtc) @@ -1359,7 +1359,7 @@ public async Task TimerDelay(bool useUtc) } } - [TestMethod] + [DataTestMethod] [DataRow(false)] [DataRow(true)] public async Task OrchestratorStartAtAcceptsAllDateTimeKinds(bool useUtc) @@ -1399,7 +1399,7 @@ public async Task OrchestratorStartAtAcceptsAllDateTimeKinds(bool useUtc) /// /// End-to-end test which validates that orchestrations run concurrently of each other (up to 100 by default). /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task OrchestrationConcurrency(bool enableExtendedSessions) @@ -1438,7 +1438,7 @@ public async Task OrchestrationConcurrency(bool enableExtendedSessions) /// /// End-to-end test which validates the orchestrator's exception handling behavior. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task HandledActivityException(bool enableExtendedSessions) @@ -1461,7 +1461,7 @@ public async Task HandledActivityException(bool enableExtendedSessions) /// /// End-to-end test which validates the handling of unhandled exceptions generated from orchestrator code. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task UnhandledOrchestrationException(bool enableExtendedSessions) @@ -1484,7 +1484,7 @@ public async Task UnhandledOrchestrationException(bool enableExtendedSessions) /// /// End-to-end test which validates the handling of unhandled exceptions generated from activity code. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task UnhandledActivityException(bool enableExtendedSessions) @@ -1507,7 +1507,7 @@ public async Task UnhandledActivityException(bool enableExtendedSessions) /// /// Fan-out/fan-in test which ensures each operation is run only once. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task FanOutToTableStorage(bool enableExtendedSessions) @@ -1551,7 +1551,7 @@ public void ValidateEventSource() /// /// End-to-end test which validates that orchestrations with <=60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task SmallTextMessagePayloads(bool enableExtendedSessions) @@ -1587,7 +1587,7 @@ public async Task SmallTextMessagePayloads(bool enableExtendedSessions) /// /// End-to-end test which validates that orchestrations with > 60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeQueueTextMessagePayloads_BlobUrl(bool enableExtendedSessions) @@ -1614,7 +1614,7 @@ public async Task LargeQueueTextMessagePayloads_BlobUrl(bool enableExtendedSessi /// /// End-to-end test which validates that orchestrations with > 60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeTableTextMessagePayloads_SizeViolation_BlobUrl(bool enableExtendedSessions) @@ -1698,7 +1698,7 @@ public async Task TagsAreAvailableInOrchestrationState() /// /// End-to-end test which validates that orchestrations with > 60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeOverallTextMessagePayloads_BlobUrl(bool enableExtendedSessions) @@ -1735,7 +1735,7 @@ await ValidateLargeMessageBlobUrlAsync( /// /// End-to-end test which validates that orchestrations with > 60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeTextMessagePayloads_FetchLargeMessages(bool enableExtendedSessions) @@ -1759,7 +1759,7 @@ public async Task LargeTextMessagePayloads_FetchLargeMessages(bool enableExtende /// /// End-to-end test which validates that orchestrations with > 60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeTableTextMessagePayloads_FetchLargeMessages(bool enableExtendedSessions) @@ -1811,7 +1811,7 @@ public async Task LargeOrchestrationTags() /// /// End-to-end test which validates that orchestrations with > 60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task NonBlobUriPayload_FetchLargeMessages_RetainsOriginalPayload(bool enableExtendedSessions) @@ -1835,7 +1835,7 @@ public async Task NonBlobUriPayload_FetchLargeMessages_RetainsOriginalPayload(bo /// /// End-to-end test which validates that orchestrations with > 60KB text message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeTextMessagePayloads_FetchLargeMessages_QueryState(bool enableExtendedSessions) @@ -1863,7 +1863,7 @@ public async Task LargeTextMessagePayloads_FetchLargeMessages_QueryState(bool en /// End-to-end test which validates that exception messages that are considered valid Urls in the Uri.TryCreate() method /// are handled with an additional Uri format check /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeTextMessagePayloads_URIFormatCheck(bool enableExtendedSessions) @@ -1927,7 +1927,7 @@ private StringBuilder GenerateMediumRandomStringPayload(int numChars = 128 * 102 /// /// End-to-end test which validates that orchestrations with > 60KB binary bytes message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeBinaryByteMessagePayloads(bool enableExtendedSessions) @@ -1957,7 +1957,7 @@ public async Task LargeBinaryByteMessagePayloads(bool enableExtendedSessions) /// /// End-to-end test which validates that orchestrations with > 60KB binary string message sizes can run successfully. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task LargeBinaryStringMessagePayloads(bool enableExtendedSessions) @@ -1989,7 +1989,7 @@ public async Task LargeBinaryStringMessagePayloads(bool enableExtendedSessions) /// /// End-to-end test which validates that a completed singleton instance can be recreated. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task RecreateCompletedInstance(bool enableExtendedSessions) @@ -2027,7 +2027,7 @@ public async Task RecreateCompletedInstance(bool enableExtendedSessions) /// /// End-to-end test which validates that a failed singleton instance can be recreated. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task RecreateFailedInstance(bool enableExtendedSessions) @@ -2062,7 +2062,7 @@ public async Task RecreateFailedInstance(bool enableExtendedSessions) /// /// End-to-end test which validates that a terminated orchestration can be recreated. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task RecreateTerminatedInstance(bool enableExtendedSessions) @@ -2106,7 +2106,7 @@ public async Task RecreateTerminatedInstance(bool enableExtendedSessions) /// /// End-to-end test which validates that a running orchestration can be recreated. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task RecreateRunningInstance(bool enableExtendedSessions) @@ -2203,7 +2203,7 @@ public async Task ExtendedSessions_SessionTimeout() /// Tests an orchestration that does two consecutive fan-out, fan-ins. /// This is a regression test for https://github.com/Azure/durabletask/issues/241. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task DoubleFanOut(bool enableExtendedSessions) @@ -2236,7 +2236,7 @@ private static async Task ValidateLargeMessageBlobUrlAsync(string taskHubName, s BlobContainerClient container = serviceClient.GetBlobContainerClient(containerName); Assert.IsTrue(await container.ExistsAsync(), $"Blob container {containerName} is expected to exist."); BlobItem blob = await container - .GetBlobsByHierarchyAsync(BlobTraits.Metadata, BlobStates.None, default, sanitizedInstanceId, default) + .GetBlobsByHierarchyAsync(BlobTraits.Metadata, BlobStates.None, delimiter: "/", sanitizedInstanceId, default) .Where(x => x.IsBlob && x.Blob.Name == sanitizedInstanceId + "/" + blobName) .Select(x => x.Blob) .SingleOrDefaultAsync(); @@ -2251,7 +2251,7 @@ private static async Task ValidateLargeMessageBlobUrlAsync(string taskHubName, s /// /// Tests the behavior of from orchestrations and activities. /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task AbortOrchestrationAndActivity(bool enableExtendedSessions) @@ -2276,7 +2276,7 @@ public async Task AbortOrchestrationAndActivity(bool enableExtendedSessions) /// /// /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task ScheduledStart_Inline(bool enableExtendedSessions) @@ -2317,7 +2317,7 @@ public async Task ScheduledStart_Inline(bool enableExtendedSessions) /// /// /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task ScheduledStart_Activity(bool enableExtendedSessions) @@ -2358,7 +2358,7 @@ public async Task ScheduledStart_Activity(bool enableExtendedSessions) /// /// /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task ScheduledStart_Activity_GetStatus_Returns_ScheduledStart(bool enableExtendedSessions) @@ -2403,7 +2403,7 @@ await Task.WhenAll( /// To recover from this, users may set `AllowReplayingTerminalInstances` to true. When this is set, DTFx will not discard /// events for terminal orchestrators, forcing a replay which eventually updates the instances table to the right state. /// - [TestMethod] + [DataTestMethod] [DataRow(true, true, true)] [DataRow(true, true, false)] [DataRow(true, false, true)] @@ -2501,7 +2501,7 @@ public async Task TestAllowReplayingTerminalInstances(bool enableExtendedSession /// the tracking store context object that is part of the orchestration session state which keeps track of the blobs. /// /// - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -2593,7 +2593,7 @@ public async Task TestWorkerFailingDuringCompleteWorkItemCallCompletedOrchestrat /// Same as but for a failed orchestration. /// /// - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -2685,7 +2685,7 @@ public async Task TestWorkerFailingDuringCompleteWorkItemCallFailedOrchestration /// /// Same as but for a terminated orchestration. /// - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -2779,7 +2779,7 @@ public async Task TestWorkerFailingDuringCompleteWorkItemCallTerminatedOrchestra /// Same as but for an orchestration with large input /// and output, which will need to be stored in blob storage. /// - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -2872,7 +2872,7 @@ public async Task TestWorkerFailingDuringCompleteWorkItemCallLargeInputOutput(bo /// Same as but for a large termination reason that /// will need to be stored in blob storage. /// - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -2969,7 +2969,7 @@ public async Task TestWorkerFailingDuringCompleteWorkItemCallLargeTerminationRea /// Same as but for a large exception message that will need /// to be stored in blob storage. /// - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -3060,7 +3060,7 @@ public async Task TestWorkerFailingDuringCompleteWorkItemCallLargeFailureReason( } } - [TestMethod] + [DataTestMethod] [DataRow(VersioningSettings.VersionMatchStrategy.Strict)] [DataRow(VersioningSettings.VersionMatchStrategy.CurrentOrOlder)] [DataRow(VersioningSettings.VersionMatchStrategy.None)] @@ -3091,7 +3091,7 @@ public async Task OrchestrationFailsWithVersionMismatch(VersioningSettings.Versi } } - [TestMethod] + [DataTestMethod] [DataRow(VersioningSettings.VersionMatchStrategy.Strict, "1.0.0")] [DataRow(VersioningSettings.VersionMatchStrategy.CurrentOrOlder, "1.0.0")] [DataRow(VersioningSettings.VersionMatchStrategy.CurrentOrOlder, "0.9.0")] @@ -3161,7 +3161,7 @@ public async Task OrchestrationRejectsWithVersionMismatch() /// /// The value to use for /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task WorkerAttemptingToUpdateInstanceTableAfterStalling(bool useInstanceEtag) @@ -3276,7 +3276,7 @@ await service.CreateTaskOrchestrationAsync( /// /// The value to use for /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task WorkerAttemptingToUpdateInstanceTableAfterStallingForSubOrchestration(bool useInstanceEtag) @@ -3417,7 +3417,7 @@ await service.CreateTaskOrchestrationAsync( } } - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task WorkerAttemptingToDequeueMessageForNonExistentInstance(bool extendedSessionsEnabled) @@ -3469,7 +3469,7 @@ await service.SendTaskOrchestrationMessageAsync( } } - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -3562,7 +3562,7 @@ await service.SendTaskOrchestrationMessageAsync( } } - [TestMethod] + [DataTestMethod] [DataRow(true, true)] [DataRow(false, true)] [DataRow(true, false)] @@ -3675,7 +3675,7 @@ await service.SendTaskOrchestrationMessageAsync( /// End-to-end test which validates a simple orchestrator function that calls an activity function /// and checks the OpenTelemetry trace information /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task OpenTelemetry_SayHelloWithActivity(bool enableExtendedSessions) @@ -3758,7 +3758,7 @@ public async Task OpenTelemetry_SayHelloWithActivity(bool enableExtendedSessions /// End-to-end test which validates a simple orchestrator function that waits for an external event /// raised through the RaiseEvent API and checks the OpenTelemetry trace information /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task OpenTelemetry_ExternalEvent_RaiseEvent(bool enableExtendedSessions) @@ -3840,7 +3840,7 @@ public async Task OpenTelemetry_ExternalEvent_RaiseEvent(bool enableExtendedSess /// /// End-to-end test which validates a simple orchestrator function that fires a timer and checks the OpenTelemetry trace information /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task OpenTelemetry_TimerFired(bool enableExtendedSessions) @@ -3919,7 +3919,7 @@ public async Task OpenTelemetry_TimerFired(bool enableExtendedSessions) /// End-to-end test which validates a simple orchestrator function that waits for an external event /// raised by calling SendEvent and checks the OpenTelemetry trace information /// - [TestMethod] + [DataTestMethod] [DataRow(true)] [DataRow(false)] public async Task OpenTelemetry_ExternalEvent_SendEvent(bool enableExtendedSessions)