Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
danielgerlag committed Apr 13, 2018
1 parent 2b19a86 commit b48bfd4
Show file tree
Hide file tree
Showing 8 changed files with 494 additions and 113 deletions.
2 changes: 1 addition & 1 deletion src/WorkflowCore/Interface/IExecutionPointerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace WorkflowCore.Interface
{
public interface IExecutionPointerFactory
{
ExecutionPointer BuildStartingPointer(WorkflowDefinition def);
ExecutionPointer BuildGenesisPointer(WorkflowDefinition def);
ExecutionPointer BuildCompensationPointer(WorkflowDefinition def, ExecutionPointer pointer, ExecutionPointer exceptionPointer, int compensationStepId);
ExecutionPointer BuildNextPointer(WorkflowDefinition def, ExecutionPointer pointer, StepOutcome outcomeTarget);
ExecutionPointer BuildChildPointer(WorkflowDefinition def, ExecutionPointer pointer, int childDefinitionId, object branch);
Expand Down
20 changes: 10 additions & 10 deletions src/WorkflowCore/Models/WorkflowStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@ public abstract class WorkflowStep
{
public abstract Type BodyType { get; }

public int Id { get; set; }
public virtual int Id { get; set; }

public string Name { get; set; }
public virtual string Name { get; set; }

public string Tag { get; set; }
public virtual string Tag { get; set; }

public List<int> Children { get; set; } = new List<int>();
public virtual List<int> Children { get; set; } = new List<int>();

public List<StepOutcome> Outcomes { get; set; } = new List<StepOutcome>();
public virtual List<StepOutcome> Outcomes { get; set; } = new List<StepOutcome>();

public List<DataMapping> Inputs { get; set; } = new List<DataMapping>();
public virtual List<DataMapping> Inputs { get; set; } = new List<DataMapping>();

public List<DataMapping> Outputs { get; set; } = new List<DataMapping>();
public virtual List<DataMapping> Outputs { get; set; } = new List<DataMapping>();

public WorkflowErrorHandling? ErrorBehavior { get; set; }
public virtual WorkflowErrorHandling? ErrorBehavior { get; set; }

public TimeSpan? RetryInterval { get; set; }
public virtual TimeSpan? RetryInterval { get; set; }

public int? CompensationStepId { get; set; }
public virtual int? CompensationStepId { get; set; }

public virtual bool ResumeChildrenAfterCompensation => true;

Expand Down
2 changes: 1 addition & 1 deletion src/WorkflowCore/Services/ExecutionPointerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace WorkflowCore.Services
public class ExecutionPointerFactory : IExecutionPointerFactory
{

public ExecutionPointer BuildStartingPointer(WorkflowDefinition def)
public ExecutionPointer BuildGenesisPointer(WorkflowDefinition def)
{
return new ExecutionPointer
{
Expand Down
7 changes: 2 additions & 5 deletions src/WorkflowCore/Services/WorkflowController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ public class WorkflowController : IWorkflowController
private readonly IQueueProvider _queueProvider;
private readonly IExecutionPointerFactory _pointerFactory;
private readonly ILogger _logger;



public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILoggerFactory loggerFactory)
{
_persistenceStore = persistenceStore;
Expand Down Expand Up @@ -72,7 +71,7 @@ public async Task<string> StartWorkflow<TData>(string workflowId, int? version,
wf.Data = TypeExtensions.GetConstructor(def.DataType, new Type[] { }).Invoke(null);
}

wf.ExecutionPointers.Add(_pointerFactory.BuildStartingPointer(def));
wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def));

string id = await _persistenceStore.CreateNewWorkflow(wf);
await _queueProvider.QueueWork(id, QueueType.Workflow);
Expand Down Expand Up @@ -148,8 +147,6 @@ public async Task<bool> ResumeWorkflow(string workflowId)
if (requeue)
await _queueProvider.QueueWork(workflowId, QueueType.Workflow);
}

return false;
}

public async Task<bool> TerminateWorkflow(string workflowId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Text;
using System.Threading;
using WorkflowCore.Interface;
using NUnit;
using FluentAssertions;
using NUnit.Framework;

Expand Down
4 changes: 2 additions & 2 deletions test/WorkflowCore.UnitTests/BasePersistenceFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public abstract class BasePersistenceFixture
protected abstract IPersistenceProvider Subject { get; }

[Fact]
public void CreateNewWorkflow()
public void CreateNewWorkflow_should_generate_id()
{
var workflow = new WorkflowInstance()
{
Expand All @@ -40,7 +40,7 @@ public void CreateNewWorkflow()
}

[Fact]
public void GetWorkflowInstance()
public void GetWorkflowInstance_should_retrieve_workflow()
{
var workflow = new WorkflowInstance()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
using FakeItEasy;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using WorkflowCore.Services;
using FluentAssertions;
using Xunit;
using WorkflowCore.Primitives;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace WorkflowCore.UnitTests.Services
{
public class ExecutionResultProcessorFixture
{

protected IExecutionResultProcessor Subject;
protected IExecutionPointerFactory PointerFactory;
protected IDateTimeProvider DateTimeProvider;
protected WorkflowOptions Options;

public ExecutionResultProcessorFixture()
{
PointerFactory = A.Fake<IExecutionPointerFactory>();
DateTimeProvider = A.Fake<IDateTimeProvider>();

Options = new WorkflowOptions();

A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now);

//config logging
var loggerFactory = new LoggerFactory();
loggerFactory.AddConsole(LogLevel.Debug);

Subject = new ExecutionResultProcessor(PointerFactory, DateTimeProvider, Options, loggerFactory);
}

[Fact(DisplayName = "Should advance workflow")]
public void should_advance_workflow()
{
//arrange
var definition = new WorkflowDefinition();
var pointer1 = new ExecutionPointer() { Active = true, StepId = 0, Status = PointerStatus.Running };
var pointer2 = new ExecutionPointer();
var outcome = new StepOutcome() { NextStep = 1 };
var step = A.Fake<WorkflowStep>();
var workflowResult = new WorkflowExecutorResult();
var instance = GivenWorkflow(pointer1);
var result = ExecutionResult.Next();

A.CallTo(() => step.Outcomes).Returns(new List<StepOutcome>() { outcome });
A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome)).Returns(pointer2);

//act
Subject.ProcessExecutionResult(instance, definition, pointer1, step, result, workflowResult);

//assert
pointer1.Active.Should().BeFalse();
pointer1.Status.Should().Be(PointerStatus.Complete);
pointer1.EndTime.Should().NotBeNull();

A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome)).MustHaveHappened();
instance.ExecutionPointers.Should().Contain(pointer2);
}

[Fact(DisplayName = "Should set persistence data")]
public void should_set_persistence_data()
{
//arrange
var persistenceData = new object();
var definition = new WorkflowDefinition();
var pointer = new ExecutionPointer() { Active = true, StepId = 0, Status = PointerStatus.Running };
var step = A.Fake<WorkflowStep>();
var workflowResult = new WorkflowExecutorResult();
var instance = GivenWorkflow(pointer);
var result = ExecutionResult.Persist(persistenceData);

//act
Subject.ProcessExecutionResult(instance, definition, pointer, step, result, workflowResult);

//assert
pointer.PersistenceData.Should().Be(persistenceData);
}

[Fact(DisplayName = "Should subscribe to event")]
public void should_subscribe_to_event()
{
//arrange
var definition = new WorkflowDefinition();
var pointer = new ExecutionPointer() { Active = true, StepId = 0, Status = PointerStatus.Running };
var step = A.Fake<WorkflowStep>();
var workflowResult = new WorkflowExecutorResult();
var instance = GivenWorkflow(pointer);
var result = ExecutionResult.WaitForEvent("Event", "Key", DateTime.Now);

//act
Subject.ProcessExecutionResult(instance, definition, pointer, step, result, workflowResult);

//assert
pointer.Status.Should().Be(PointerStatus.WaitingForEvent);
pointer.Active.Should().BeFalse();
pointer.EventName.Should().Be("Event");
pointer.EventKey.Should().Be("Key");
workflowResult.Subscriptions.Should().Contain(x => x.StepId == pointer.StepId && x.EventName == "Event" && x.EventKey == "Key");
}

[Fact(DisplayName = "Should select correct outcomes")]
public void should_select_correct_outcomes()
{
//arrange
var definition = new WorkflowDefinition();
var pointer1 = new ExecutionPointer() { Active = true, StepId = 0, Status = PointerStatus.Running };
var pointer2 = new ExecutionPointer();
var pointer3 = new ExecutionPointer();
var outcome1 = new StepOutcome() { NextStep = 1, Value = data => 10 };
var outcome2 = new StepOutcome() { NextStep = 2, Value = data => 20 };
var step = A.Fake<WorkflowStep>();
var workflowResult = new WorkflowExecutorResult();
var instance = GivenWorkflow(pointer1);
var result = ExecutionResult.Outcome(20);

A.CallTo(() => step.Outcomes).Returns(new List<StepOutcome>() { outcome1, outcome2 });
A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome1)).Returns(pointer2);
A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome2)).Returns(pointer3);

//act
Subject.ProcessExecutionResult(instance, definition, pointer1, step, result, workflowResult);

//assert
pointer1.Active.Should().BeFalse();
pointer1.Status.Should().Be(PointerStatus.Complete);
pointer1.EndTime.Should().NotBeNull();

A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome1)).MustNotHaveHappened();
A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome2)).MustHaveHappened();
instance.ExecutionPointers.Should().NotContain(pointer2);
instance.ExecutionPointers.Should().Contain(pointer3);
}

[Fact(DisplayName = "Should sleep pointer")]
public void should_sleep_pointer()
{
//arrange
var persistenceData = new object();
var definition = new WorkflowDefinition();
var pointer = new ExecutionPointer() { Active = true, StepId = 0, Status = PointerStatus.Running };
var step = A.Fake<WorkflowStep>();
var workflowResult = new WorkflowExecutorResult();
var instance = GivenWorkflow(pointer);
var result = ExecutionResult.Sleep(TimeSpan.FromMinutes(5), persistenceData);

//act
Subject.ProcessExecutionResult(instance, definition, pointer, step, result, workflowResult);

//assert
pointer.Status.Should().Be(PointerStatus.Sleeping);
pointer.SleepUntil.Should().NotBeNull();
}

[Fact(DisplayName = "Should branch children")]
public void should_branch_children()
{
//arrange
var branch = 10;
var child = 2;
var definition = new WorkflowDefinition();
var pointer = new ExecutionPointer() { Active = true, StepId = 0, Status = PointerStatus.Running };
var childPointer = new ExecutionPointer();
var step = A.Fake<WorkflowStep>();
var workflowResult = new WorkflowExecutorResult();
var instance = GivenWorkflow(pointer);
var result = ExecutionResult.Branch(new List<object>() { branch }, null);

A.CallTo(() => step.Children).Returns(new List<int>() { child });
A.CallTo(() => PointerFactory.BuildChildPointer(definition, pointer, child, branch)).Returns(childPointer);

//act
Subject.ProcessExecutionResult(instance, definition, pointer, step, result, workflowResult);

//assert
A.CallTo(() => PointerFactory.BuildChildPointer(definition, pointer, child, branch)).MustHaveHappened();
instance.ExecutionPointers.Should().Contain(childPointer);
}


private static WorkflowInstance GivenWorkflow(ExecutionPointer pointer)
{
return new WorkflowInstance
{
Status = WorkflowStatus.Runnable,
ExecutionPointers = new List<ExecutionPointer>()
{
pointer
}
};
}
}
}
Loading

0 comments on commit b48bfd4

Please sign in to comment.