Skip to content

Commit 29531c0

Browse files
committed
Add unit tests for call stack depth calculations and persistence
- Add `WorkflowExecutionContextTests` to verify correct calculation of call stack depth during activity execution. - Add `WorkflowStateExtractorTests` to ensure call stack depth is preserved during state extraction and application.
1 parent 23a59cc commit 29531c0

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using Elsa.Common;
2+
using Elsa.Testing.Shared;
3+
using Elsa.Workflows.Activities;
4+
using Elsa.Workflows.Options;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Xunit;
7+
8+
namespace Elsa.Workflows.Core.UnitTests.Contexts;
9+
10+
public class WorkflowExecutionContextTests
11+
{
12+
[Fact]
13+
public async Task CreateActivityExecutionContextAsync_CalculatesCallStackDepth_Correctly()
14+
{
15+
// Arrange
16+
var activityA = new WriteLine("A");
17+
var activityB = new WriteLine("B");
18+
var activityC = new WriteLine("C");
19+
var root = new Sequence { Activities = { activityA, activityB, activityC } };
20+
var fixture = new ActivityTestFixture(root);
21+
var contextRoot = await fixture.BuildAsync();
22+
var workflowExecutionContext = contextRoot.WorkflowExecutionContext;
23+
24+
// Act
25+
// Level 0 (already created by fixture.BuildAsync for the root activity, but let's create explicitly for clarity)
26+
var contextA = await workflowExecutionContext.CreateActivityExecutionContextAsync(activityA);
27+
28+
// Level 1: B scheduled by A
29+
var contextB = await workflowExecutionContext.CreateActivityExecutionContextAsync(activityB, new ActivityInvocationOptions
30+
{
31+
SchedulingActivityExecutionId = contextA.Id
32+
});
33+
34+
// Level 2: C scheduled by B
35+
var contextC = await workflowExecutionContext.CreateActivityExecutionContextAsync(activityC, new ActivityInvocationOptions
36+
{
37+
SchedulingActivityExecutionId = contextB.Id
38+
});
39+
40+
// Assert
41+
Assert.Equal(0, contextA.CallStackDepth);
42+
Assert.Equal(1, contextB.CallStackDepth);
43+
Assert.Equal(2, contextC.CallStackDepth);
44+
}
45+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Elsa.Common;
2+
using Elsa.Testing.Shared;
3+
using Elsa.Workflows.Activities;
4+
using Elsa.Workflows.Services;
5+
using Elsa.Workflows.State;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Xunit;
8+
9+
namespace Elsa.Workflows.Core.UnitTests.Services;
10+
11+
public class WorkflowStateExtractorTests
12+
{
13+
[Fact]
14+
public async Task Extract_And_Apply_PreservesCallStackDepth()
15+
{
16+
// Arrange
17+
var root = new WriteLine("root");
18+
var fixture = new ActivityTestFixture(root);
19+
var contextRoot = await fixture.BuildAsync();
20+
var workflowExecutionContext = contextRoot.WorkflowExecutionContext;
21+
22+
var contextA = await workflowExecutionContext.CreateActivityExecutionContextAsync(root);
23+
contextA.CallStackDepth = 10; // Manually set for testing persistence
24+
workflowExecutionContext.AddActivityExecutionContext(contextA);
25+
26+
var extractor = workflowExecutionContext.GetRequiredService<IWorkflowStateExtractor>();
27+
28+
// Act
29+
var state = extractor.Extract(workflowExecutionContext);
30+
31+
// Create a new context to apply the state to
32+
var newWorkflowExecutionContext = await WorkflowExecutionContext.CreateAsync(
33+
workflowExecutionContext.ServiceProvider,
34+
workflowExecutionContext.WorkflowGraph,
35+
state.Id,
36+
CancellationToken.None
37+
);
38+
39+
await extractor.ApplyAsync(newWorkflowExecutionContext, state);
40+
41+
// Assert
42+
var restoredContextA = newWorkflowExecutionContext.ActivityExecutionContexts.FirstOrDefault(x => x.Id == contextA.Id);
43+
Assert.NotNull(restoredContextA);
44+
Assert.Equal(10, restoredContextA.CallStackDepth);
45+
}
46+
}

0 commit comments

Comments
 (0)