183 lines
6.7 KiB
C#
183 lines
6.7 KiB
C#
using Elsa.Testing.Shared;
|
|
using Elsa.Workflows;
|
|
using Elsa.Workflows.Activities;
|
|
using Xunit.Abstractions;
|
|
using Parallel = Elsa.Workflows.Activities.Parallel;
|
|
|
|
namespace Elsa.Activities.IntegrationTests;
|
|
|
|
public class ParallelTests(ITestOutputHelper testOutputHelper)
|
|
{
|
|
private readonly WorkflowTestFixture _fixture = new(testOutputHelper);
|
|
|
|
[Fact(DisplayName = "Parallel executes all child activities and completes")]
|
|
public async Task Parallel_ExecutesAllChildren_AndCompletes()
|
|
{
|
|
// Arrange
|
|
var parallel = new Parallel(
|
|
new WriteLine("Activity 1"),
|
|
new WriteLine("Activity 2"),
|
|
new WriteLine("Activity 3")
|
|
);
|
|
|
|
// Act
|
|
var result = await _fixture.RunActivityAsync(parallel);
|
|
|
|
// Assert
|
|
var journal = result.Journal;
|
|
var parallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity is Parallel);
|
|
|
|
Assert.NotNull(parallelContext);
|
|
Assert.Equal(ActivityStatus.Completed, parallelContext.Status);
|
|
Assert.Equal(3, _fixture.CapturingTextWriter.Lines.Count);
|
|
Assert.Contains("Activity 1", _fixture.CapturingTextWriter.Lines);
|
|
Assert.Contains("Activity 2", _fixture.CapturingTextWriter.Lines);
|
|
Assert.Contains("Activity 3", _fixture.CapturingTextWriter.Lines);
|
|
}
|
|
|
|
[Fact(DisplayName = "Parallel completes when empty")]
|
|
public async Task Parallel_Completes_WhenEmpty()
|
|
{
|
|
// Arrange
|
|
var parallel = new Parallel();
|
|
|
|
// Act
|
|
var result = await _fixture.RunActivityAsync(parallel);
|
|
|
|
// Assert
|
|
var journal = result.Journal;
|
|
var parallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity is Parallel);
|
|
|
|
Assert.NotNull(parallelContext);
|
|
Assert.Equal(ActivityStatus.Completed, parallelContext.Status);
|
|
Assert.Empty(_fixture.CapturingTextWriter.Lines);
|
|
}
|
|
|
|
[Fact(DisplayName = "Parallel executes single child activity and completes")]
|
|
public async Task Parallel_ExecutesSingleChild_AndCompletes()
|
|
{
|
|
// Arrange
|
|
var parallel = new Parallel(
|
|
new WriteLine("Single Activity")
|
|
);
|
|
|
|
// Act
|
|
var result = await _fixture.RunActivityAsync(parallel);
|
|
|
|
// Assert
|
|
var journal = result.Journal;
|
|
var parallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity is Parallel);
|
|
|
|
Assert.NotNull(parallelContext);
|
|
Assert.Equal(ActivityStatus.Completed, parallelContext.Status);
|
|
Assert.Single(_fixture.CapturingTextWriter.Lines);
|
|
Assert.Equal("Single Activity", _fixture.CapturingTextWriter.Lines.Single());
|
|
}
|
|
|
|
[Fact(DisplayName = "Parallel executes multiple different activity types")]
|
|
public async Task Parallel_ExecutesMixedActivityTypes_AndCompletes()
|
|
{
|
|
// Arrange
|
|
var parallel = new Parallel(
|
|
new WriteLine("First"),
|
|
new SetName("TestName"),
|
|
new WriteLine("Second")
|
|
);
|
|
|
|
// Act
|
|
var result = await _fixture.RunActivityAsync(parallel);
|
|
|
|
// Assert
|
|
var journal = result.Journal;
|
|
var parallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity is Parallel);
|
|
|
|
Assert.NotNull(parallelContext);
|
|
Assert.Equal(ActivityStatus.Completed, parallelContext.Status);
|
|
Assert.Equal(2, _fixture.CapturingTextWriter.Lines.Count);
|
|
Assert.Contains("First", _fixture.CapturingTextWriter.Lines);
|
|
Assert.Contains("Second", _fixture.CapturingTextWriter.Lines);
|
|
}
|
|
|
|
[Fact(DisplayName = "Parallel completes only after all children complete")]
|
|
public async Task Parallel_CompletesOnlyAfterAllChildrenComplete()
|
|
{
|
|
// Arrange
|
|
var parallel = new Parallel(
|
|
new WriteLine("Child 1"),
|
|
new WriteLine("Child 2"),
|
|
new WriteLine("Child 3"),
|
|
new WriteLine("Child 4")
|
|
);
|
|
|
|
// Act
|
|
var result = await _fixture.RunActivityAsync(parallel);
|
|
|
|
// Assert
|
|
var journal = result.Journal;
|
|
var parallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity is Parallel);
|
|
|
|
Assert.NotNull(parallelContext);
|
|
Assert.Equal(ActivityStatus.Completed, parallelContext.Status);
|
|
Assert.Equal(4, _fixture.CapturingTextWriter.Lines.Count);
|
|
}
|
|
|
|
[Fact(DisplayName = "Parallel executes nested Parallel activities")]
|
|
public async Task Parallel_ExecutesNestedParallel_AndCompletes()
|
|
{
|
|
// Arrange
|
|
var innerParallel = new Parallel(
|
|
new WriteLine("Inner 1"),
|
|
new WriteLine("Inner 2")
|
|
);
|
|
|
|
var outerParallel = new Parallel(
|
|
new WriteLine("Outer 1"),
|
|
innerParallel,
|
|
new WriteLine("Outer 2")
|
|
);
|
|
|
|
// Act
|
|
var result = await _fixture.RunActivityAsync(outerParallel);
|
|
|
|
// Assert
|
|
var journal = result.Journal;
|
|
var outerParallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity == outerParallel);
|
|
var innerParallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity == innerParallel);
|
|
|
|
Assert.NotNull(outerParallelContext);
|
|
Assert.NotNull(innerParallelContext);
|
|
Assert.Equal(ActivityStatus.Completed, outerParallelContext.Status);
|
|
Assert.Equal(ActivityStatus.Completed, innerParallelContext.Status);
|
|
Assert.Equal(4, _fixture.CapturingTextWriter.Lines.Count);
|
|
Assert.Contains("Outer 1", _fixture.CapturingTextWriter.Lines);
|
|
Assert.Contains("Outer 2", _fixture.CapturingTextWriter.Lines);
|
|
Assert.Contains("Inner 1", _fixture.CapturingTextWriter.Lines);
|
|
Assert.Contains("Inner 2", _fixture.CapturingTextWriter.Lines);
|
|
}
|
|
|
|
[Fact(DisplayName = "Parallel remains in Running state when a child activity faults")]
|
|
public async Task Parallel_RemainsRunning_WhenChildFaults()
|
|
{
|
|
// Arrange
|
|
var parallel = new Parallel(
|
|
new WriteLine("Before Fault"),
|
|
new Fault { Message = new("Test fault") },
|
|
new WriteLine("After Fault")
|
|
);
|
|
|
|
// Act
|
|
var result = await _fixture.RunActivityAsync(parallel);
|
|
|
|
// Assert
|
|
var journal = result.Journal;
|
|
var parallelContext = journal.ActivityExecutionContexts.FirstOrDefault(x => x.Activity is Parallel);
|
|
|
|
Assert.NotNull(parallelContext);
|
|
Assert.Equal(ActivityStatus.Running, parallelContext.Status);
|
|
Assert.Equal(1, parallelContext.AggregateFaultCount);
|
|
// The non-faulted activities should still execute
|
|
Assert.Contains("Before Fault", _fixture.CapturingTextWriter.Lines);
|
|
Assert.Contains("After Fault", _fixture.CapturingTextWriter.Lines);
|
|
}
|
|
}
|