diff --git a/Test/DurableTask.Core.Tests/TestTaskEntityDispatcher.cs b/Test/DurableTask.Core.Tests/TestTaskEntityDispatcher.cs
index 13c886baa..42cc0b2c9 100644
--- a/Test/DurableTask.Core.Tests/TestTaskEntityDispatcher.cs
+++ b/Test/DurableTask.Core.Tests/TestTaskEntityDispatcher.cs
@@ -1,25 +1,88 @@
using DurableTask.Core.Entities;
+using DurableTask.Core.Entities.OperationFormat;
using DurableTask.Core.History;
+using DurableTask.Core.Logging;
+using DurableTask.Core.Middleware;
using DurableTask.Emulator;
+using DurableTask.Test.Orchestrations;
+using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Collections.Generic;
+using static DurableTask.Core.TaskEntityDispatcher;
namespace DurableTask.Core.Tests
{
[TestClass]
public class TestTaskEntityDispatcher
{
+ ///
+ /// Utiliy function to create a TaskEntityDispatcher instance. To be expanded upon as per testing needs.
+ ///
+ ///
+ private TaskEntityDispatcher GetTaskEntityDispatcher()
+ {
+ // TODO: these should probably be injectable parameters to this method,
+ // initialized with sensible defaults if not provided
+ var service = new LocalOrchestrationService();
+ ILoggerFactory loggerFactory = null;
+ var entityManager = new NameVersionObjectManager();
+ var entityMiddleware = new DispatchMiddlewarePipeline();
+ var logger = new LogHelper(loggerFactory?.CreateLogger("DurableTask.Core"));
+
+ TaskEntityDispatcher dispatcher = new TaskEntityDispatcher(
+ service, entityManager, entityMiddleware, logger, ErrorPropagationMode.UseFailureDetails);
+ return dispatcher;
+ }
+
+ ///
+ /// See: https://github.com/Azure/durabletask/pull/1080
+ /// This test is motivated by a regression where Entities
+ /// that scheduled sub-orchestrators would incorrectly set
+ /// the FireAndForget tag on the ExecutionStartedEvent, causing
+ /// them to then receive a SubOrchestrationCompleted event, which
+ /// they did not know how to handle. Eventually, this led to them deleting
+ /// their own state. This test checks against that case.
+ ///
[TestMethod]
- public void TestScheduleOrchestration()
+ public void TestEntityDoesNotSetFireAndForgetTags()
{
- var service = new LocalOrchestrationService();
+ TaskEntityDispatcher dispatcher = GetTaskEntityDispatcher();
+
+ // Prepare effects
+ var effects = new WorkItemEffects();
+ effects.taskIdCounter = 0;
+ effects.InstanceMessages = new List();
+
+ // Prepare runtime state
+ var mockEntityStartEvent = new ExecutionStartedEvent(-1, null)
+ {
+ OrchestrationInstance = new OrchestrationInstance(),
+ Name = "testentity",
+ Version = "1.0",
+ };
+ var runtimeState = new OrchestrationRuntimeState();
+ runtimeState.AddEvent(mockEntityStartEvent);
+
+ // Prepare action.
+ // This mocks starting a new orchestration from an entity.
+ var action = new StartNewOrchestrationOperationAction()
+ {
+ InstanceId = "testsample",
+ Name = "test",
+ Version = "1.0",
+ Input = null,
+ };
+
+ // Invoke the dispatcher and obtain resulting event
+ dispatcher.ProcessSendStartMessage(effects, runtimeState, action);
+ HistoryEvent resultEvent = effects.InstanceMessages[0].Event;
- var entityTestHelper = new EntityTestHelper(service);
- var testEvent = entityTestHelper.TestScheduleOrchestrationTags();
+ Assert.IsInstanceOfType(resultEvent, typeof(ExecutionStartedEvent));
+ var executionStartedEvent = (ExecutionStartedEvent)resultEvent;
- Assert.IsInstanceOfType(testEvent, typeof(ExecutionStartedEvent));
- var testEventTags = (ExecutionStartedEvent)testEvent;
- bool containsKey = testEventTags.Tags.ContainsKey(OrchestrationTags.FireAndForget);
- Assert.IsTrue(containsKey);
+ // The resulting event should not contain a fire and forget tag
+ bool hasFireAndForgetTag = executionStartedEvent.Tags.ContainsKey(OrchestrationTags.FireAndForget);
+ Assert.IsFalse(hasFireAndForgetTag);
}
}
}
diff --git a/src/DurableTask.Core/Entities/EntityTestHelper.cs b/src/DurableTask.Core/Entities/EntityTestHelper.cs
deleted file mode 100644
index a717ae20f..000000000
--- a/src/DurableTask.Core/Entities/EntityTestHelper.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using DurableTask.Core.History;
-using DurableTask.Core.Logging;
-using DurableTask.Core.Middleware;
-using Microsoft.Extensions.Logging;
-
-namespace DurableTask.Core.Entities
-{
- ///
- /// Class to help test TaskEntityDispatcher.
- ///
- public class EntityTestHelper
- {
- IOrchestrationService orchestrationService;
- TaskEntityDispatcher dispatcher;
-
- ///
- /// Constructor for EntityTestHelper
- ///
- /// The for initialize TaskEntityDispatcher instance.
- public EntityTestHelper(IOrchestrationService service)
- {
- this.orchestrationService = service;
- this.dispatcher = CreateTestEntityDispatcherInstance();
- }
-
- ///
- /// Create an instance of the TaskEntityDispatcher class for testing.
- ///
- /// Instance created for testing.
- public TaskEntityDispatcher CreateTestEntityDispatcherInstance()
- {
- ILoggerFactory loggerFactory = null;
- var entityManager = new NameVersionObjectManager();
- var entityMiddleware = new DispatchMiddlewarePipeline();
- var logger = new LogHelper(loggerFactory?.CreateLogger("DurableTask.Core"));
-
- return new TaskEntityDispatcher
- (
- this.orchestrationService,
- entityManager,
- entityMiddleware,
- logger,
- ErrorPropagationMode.SerializeExceptions);
- }
-
- ///
- /// Method to test orchestration settings when entities schedule it.
- ///
- /// HistoryEvent contains the scheduled message.
- public HistoryEvent TestScheduleOrchestrationTags()
- {
- return this.dispatcher.TestScheduleSendEvent();
- }
- }
-}
diff --git a/src/DurableTask.Core/TaskEntityDispatcher.cs b/src/DurableTask.Core/TaskEntityDispatcher.cs
index f04843566..a7ecb5267 100644
--- a/src/DurableTask.Core/TaskEntityDispatcher.cs
+++ b/src/DurableTask.Core/TaskEntityDispatcher.cs
@@ -182,7 +182,7 @@ async Task OnProcessWorkItemSessionAsync(TaskOrchestrationWorkItem workItem)
}
}
- class WorkItemEffects
+ internal class WorkItemEffects
{
public List ActivityMessages;
public List TimerMessages;
@@ -794,7 +794,7 @@ void ProcessSendEventMessage(WorkItemEffects effects, OrchestrationInstance dest
});
}
- void ProcessSendStartMessage(WorkItemEffects effects, OrchestrationRuntimeState runtimeState, StartNewOrchestrationOperationAction action)
+ internal void ProcessSendStartMessage(WorkItemEffects effects, OrchestrationRuntimeState runtimeState, StartNewOrchestrationOperationAction action)
{
OrchestrationInstance destination = new OrchestrationInstance()
{
@@ -883,35 +883,5 @@ await this.dispatchPipeline.RunAsync(dispatchContext, async _ =>
return result;
}
-
- ///
- /// Test only.
- ///
- internal HistoryEvent TestScheduleSendEvent()
- {
- // Initialize arguments to pass to ProcessSendStartMessage().
- var effects = new WorkItemEffects();
- effects.taskIdCounter = 0;
- effects.InstanceMessages = new List();
-
- var mockEntityStartEvent = new ExecutionStartedEvent(-1, null)
- {
- OrchestrationInstance = new OrchestrationInstance(),
- Name = "testentity",
- Version = "1.0",
- };
- var runtimeState = new OrchestrationRuntimeState();
- runtimeState.AddEvent(mockEntityStartEvent);
- var action = new StartNewOrchestrationOperationAction()
- {
- InstanceId = "testsample",
- Name = "test",
- Version = "1.0",
- Input = null,
- };
-
- this.ProcessSendStartMessage(effects, runtimeState,action);
- return effects.InstanceMessages[0].Event;
- }
}
}
diff --git a/test/DurableTask.SqlServer.Tests/DurableTask.SqlServer.Tests.csproj b/test/DurableTask.SqlServer.Tests/DurableTask.SqlServer.Tests.csproj
index cf578db09..e698b6266 100644
--- a/test/DurableTask.SqlServer.Tests/DurableTask.SqlServer.Tests.csproj
+++ b/test/DurableTask.SqlServer.Tests/DurableTask.SqlServer.Tests.csproj
@@ -23,7 +23,7 @@
-
+