Skip to content

Commit

Permalink
Added async conditions support for If
Browse files Browse the repository at this point in the history
  • Loading branch information
Greybird authored and phatboyg committed Mar 3, 2019
1 parent 6091a53 commit b1c666a
Show file tree
Hide file tree
Showing 13 changed files with 326 additions and 21 deletions.
92 changes: 92 additions & 0 deletions src/Automatonymous.Tests/Condition_Specs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,98 @@ class Start
}


class StartedExplicitFilter
{
}
}

[TestFixture]
public class Using_an_async_condition_in_a_state_machine
{
[Test]
public async Task Should_allow_the_condition_to_be_used()
{
await _machine.RaiseEvent(_instance, _machine.Started, new Start {InitializeOnly = true});

Assert.That(_instance.CurrentState, Is.EqualTo(_machine.Initialized));
}

[Test]
public async Task Should_work()
{
await _machine.RaiseEvent(_instance, _machine.Started, new Start());

Assert.That(_instance.CurrentState, Is.EqualTo(_machine.Running));
}

[Test]
public async Task Should_allow_if_condition_to_be_evaluated()
{
await _machine.RaiseEvent(_instance, _machine.ExplicitFilterStarted, new StartedExplicitFilter());

Assert.That(_instance.CurrentState, Is.Not.EqualTo(_machine.ShouldNotBeHere));
}

[SetUp]
public void Specifying_an_event_activity()
{
_instance = new Instance();
_machine = new InstanceStateMachine();
}

Instance _instance;
InstanceStateMachine _machine;


class Instance
{
public bool InitializeOnly { get; set; }
public State CurrentState { get; set; }
}


class InstanceStateMachine :
AutomatonymousStateMachine<Instance>
{
public InstanceStateMachine()
{
During(Initial,
When(Started)
.Then(context => context.Instance.InitializeOnly = context.Data.InitializeOnly)
.IfAsync(context => Task.FromResult(context.Data.InitializeOnly), x => x.Then(context => Console.WriteLine("Initializing Only!")))
.TransitionTo(Initialized));

During(Initial,
When(ExplicitFilterStarted, context => true)
.IfAsync(context => Task.FromResult(false), binder => binder
.Then(context => Console.WriteLine("Should not be here!"))
.TransitionTo(ShouldNotBeHere))
.IfAsync(context => Task.FromResult(true), binder => binder.Then(context => Console.WriteLine("Initializing Only!"))));

During(Running,
When(Finish)
.Finalize());

WhenEnter(Initialized, x => x.IfAsync(context => Task.FromResult(!context.Instance.InitializeOnly), b => b.TransitionTo(Running)));
}

public State Running { get; private set; }
public State Initialized { get; private set; }
public State ShouldNotBeHere { get; private set; }

public Event<Start> Started { get; private set; }
public Event<StartedExplicitFilter> ExplicitFilterStarted { get; private set; }

public Event Finish { get; private set; }
}


class Start
{
public bool InitializeOnly { get; set; }
}


class StartedExplicitFilter
{
}
Expand Down
21 changes: 21 additions & 0 deletions src/Automatonymous.Tests/Exception_Specs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace Automatonymous.Tests
{
using System;
using System.Threading.Tasks;
using GreenPipes;
using GreenPipes.Introspection;
using NUnit.Framework;
Expand Down Expand Up @@ -50,6 +51,7 @@ public Instance()
public bool ShouldNotBeCalled { get; set; }

public bool CalledThenClause { get; set; }
public bool CalledSecondThenClause { get; set; }
}


Expand All @@ -67,6 +69,9 @@ public InstanceStateMachine()
.If(context => true, b => b
.Then(context => context.Instance.CalledThenClause = true)
)
.IfAsync(context => Task.FromResult(true), b => b
.Then(context => context.Instance.CalledSecondThenClause = true)
)
.Then(context =>
{
context.Instance.ExceptionMessage = context.Exception.Message;
Expand Down Expand Up @@ -133,6 +138,12 @@ public void Should_have_called_the_first_if_block()
{
Assert.IsTrue(_instance.CalledThenClause);
}

[Test]
public void Should_have_called_the_async_if_block()
{
Assert.IsTrue(_instance.CalledSecondThenClause);
}
}

[TestFixture]
Expand Down Expand Up @@ -304,6 +315,7 @@ public Instance()
public State CurrentState { get; set; }

public bool CalledThenClause { get; set; }
public bool CalledSecondThenClause { get; set; }
}


Expand All @@ -328,6 +340,9 @@ public InstanceStateMachine()
.If(context => true, b => b
.Then(context => context.Instance.CalledThenClause = true)
)
.IfAsync(context => Task.FromResult(true), b => b
.Then(context => context.Instance.CalledSecondThenClause = true)
)
.Then(context =>
{
context.Instance.ExceptionMessage = context.Exception.Message;
Expand Down Expand Up @@ -377,5 +392,11 @@ public void Should_have_called_the_first_if_block()
{
Assert.IsTrue(_instance.CalledThenClause);
}

[Test]
public void Should_have_called_the_async_if_block()
{
Assert.IsTrue(_instance.CalledSecondThenClause);
}
}
}
14 changes: 7 additions & 7 deletions src/Automatonymous/Activities/ConditionActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public class ConditionActivity<TInstance> :
where TInstance : class
{
readonly Behavior<TInstance> _behavior;
readonly StateMachineCondition<TInstance> _condition;
readonly StateMachineAsyncCondition<TInstance> _condition;

public ConditionActivity(StateMachineCondition<TInstance> condition, Behavior<TInstance> behavior)
public ConditionActivity(StateMachineAsyncCondition<TInstance> condition, Behavior<TInstance> behavior)
{
_condition = condition;
_behavior = behavior;
Expand All @@ -43,15 +43,15 @@ void Visitable.Accept(StateMachineVisitor visitor)

async Task Activity<TInstance>.Execute(BehaviorContext<TInstance> context, Behavior<TInstance> next)
{
if (_condition(context))
if (await _condition(context).ConfigureAwait(false))
await _behavior.Execute(context).ConfigureAwait(false);

await next.Execute(context).ConfigureAwait(false);
}

async Task Activity<TInstance>.Execute<T>(BehaviorContext<TInstance, T> context, Behavior<TInstance, T> next)
{
if (_condition(context))
if (await _condition(context).ConfigureAwait(false))
await _behavior.Execute(context).ConfigureAwait(false);

await next.Execute(context).ConfigureAwait(false);
Expand All @@ -75,9 +75,9 @@ public class ConditionActivity<TInstance, TData> :
where TInstance : class
{
readonly Behavior<TInstance> _behavior;
readonly StateMachineCondition<TInstance, TData> _condition;
readonly StateMachineAsyncCondition<TInstance, TData> _condition;

public ConditionActivity(StateMachineCondition<TInstance, TData> condition, Behavior<TInstance> behavior)
public ConditionActivity(StateMachineAsyncCondition<TInstance, TData> condition, Behavior<TInstance> behavior)
{
_condition = condition;
_behavior = behavior;
Expand Down Expand Up @@ -105,7 +105,7 @@ async Task Activity<TInstance>.Execute<T>(BehaviorContext<TInstance, T> context,
var behaviorContext = context as BehaviorContext<TInstance, TData>;
if (behaviorContext != null)
{
if (_condition(behaviorContext))
if (await _condition(behaviorContext).ConfigureAwait(false))
await _behavior.Execute(behaviorContext).ConfigureAwait(false);
}

Expand Down
14 changes: 7 additions & 7 deletions src/Automatonymous/Activities/ConditionExceptionActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public class ConditionExceptionActivity<TInstance, TConditionException> :
where TConditionException : Exception
{
readonly Behavior<TInstance> _behavior;
readonly StateMachineExceptionCondition<TInstance, TConditionException> _condition;
readonly StateMachineAsyncExceptionCondition<TInstance, TConditionException> _condition;

public ConditionExceptionActivity(StateMachineExceptionCondition<TInstance, TConditionException> condition, Behavior<TInstance> behavior)
public ConditionExceptionActivity(StateMachineAsyncExceptionCondition<TInstance, TConditionException> condition, Behavior<TInstance> behavior)
{
_condition = condition;
_behavior = behavior;
Expand Down Expand Up @@ -58,7 +58,7 @@ async Task Activity<TInstance>.Faulted<TException>(BehaviorExceptionContext<TIns
var behaviorContext = context as BehaviorExceptionContext<TInstance, TConditionException>;
if (behaviorContext != null)
{
if (_condition(behaviorContext))
if (await _condition(behaviorContext).ConfigureAwait(false))
{
await _behavior.Faulted(context).ConfigureAwait(false);
}
Expand All @@ -73,7 +73,7 @@ async Task Activity<TInstance>.Faulted<T, TException>(BehaviorExceptionContext<T
var behaviorContext = context as BehaviorExceptionContext<TInstance, T, TConditionException>;
if (behaviorContext != null)
{
if (_condition(behaviorContext))
if (await _condition(behaviorContext).ConfigureAwait(false))
{
await _behavior.Faulted(context).ConfigureAwait(false);
}
Expand All @@ -90,9 +90,9 @@ public class ConditionExceptionActivity<TInstance, TData, TConditionException> :
where TConditionException : Exception
{
readonly Behavior<TInstance> _behavior;
readonly StateMachineExceptionCondition<TInstance, TData, TConditionException> _condition;
readonly StateMachineAsyncExceptionCondition<TInstance, TData, TConditionException> _condition;

public ConditionExceptionActivity(StateMachineExceptionCondition<TInstance, TData, TConditionException> condition, Behavior<TInstance> behavior)
public ConditionExceptionActivity(StateMachineAsyncExceptionCondition<TInstance, TData, TConditionException> condition, Behavior<TInstance> behavior)
{
_condition = condition;
_behavior = behavior;
Expand Down Expand Up @@ -131,7 +131,7 @@ async Task Activity<TInstance>.Faulted<T, TException>(BehaviorExceptionContext<T
var behaviorContext = context as BehaviorExceptionContext<TInstance, TData, TConditionException>;
if (behaviorContext != null)
{
if (_condition(behaviorContext))
if (await _condition(behaviorContext).ConfigureAwait(false))
{
await _behavior.Faulted(context).ConfigureAwait(false);
}
Expand Down
26 changes: 26 additions & 0 deletions src/Automatonymous/Binders/CatchExceptionActivityBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ public ExceptionActivityBinder<TInstance, TException> If(

return new CatchExceptionActivityBinder<TInstance, TException>(_machine, _event, _activities, conditionBinder);
}

public ExceptionActivityBinder<TInstance, TException> IfAsync(
StateMachineAsyncExceptionCondition<TInstance, TException> condition,
Func<ExceptionActivityBinder<TInstance, TException>, ExceptionActivityBinder<TInstance, TException>> activityCallback)
{
ExceptionActivityBinder<TInstance, TException> binder = new CatchExceptionActivityBinder<TInstance, TException>(_machine, _event);

binder = activityCallback(binder);

var conditionBinder = new ConditionalExceptionActivityBinder<TInstance, TException>(_event, condition, binder);

return new CatchExceptionActivityBinder<TInstance, TException>(_machine, _event, _activities, conditionBinder);
}
}


Expand Down Expand Up @@ -167,5 +180,18 @@ public ExceptionActivityBinder<TInstance, TData, TException> If(StateMachineExce

return new CatchExceptionActivityBinder<TInstance, TData, TException>(_machine, _event, _activities, conditionBinder);
}

public ExceptionActivityBinder<TInstance, TData, TException> IfAsync(StateMachineAsyncExceptionCondition<TInstance, TData, TException> condition,
Func<ExceptionActivityBinder<TInstance, TData, TException>, ExceptionActivityBinder<TInstance, TData, TException>> activityCallback)
{
ExceptionActivityBinder<TInstance, TData, TException> binder =
new CatchExceptionActivityBinder<TInstance, TData, TException>(_machine, _event);

binder = activityCallback(binder);

var conditionBinder = new ConditionalExceptionActivityBinder<TInstance, TData, TException>(_event, condition, binder);

return new CatchExceptionActivityBinder<TInstance, TData, TException>(_machine, _event, _activities, conditionBinder);
}
}
}
16 changes: 14 additions & 2 deletions src/Automatonymous/Binders/ConditionalActivityBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// specific language governing permissions and limitations under the License.
namespace Automatonymous.Binders
{
using System.Threading.Tasks;
using Activities;
using Behaviors;

Expand All @@ -21,10 +22,15 @@ public class ConditionalActivityBinder<TInstance> :
where TInstance : class
{
readonly EventActivities<TInstance> _activities;
readonly StateMachineCondition<TInstance> _condition;
readonly StateMachineAsyncCondition<TInstance> _condition;
readonly Event _event;

public ConditionalActivityBinder(Event @event, StateMachineCondition<TInstance> condition, EventActivities<TInstance> activities)
: this(@event, context => Task.FromResult(condition(context)), activities)
{
}

public ConditionalActivityBinder(Event @event, StateMachineAsyncCondition<TInstance> condition, EventActivities<TInstance> activities)
{
_activities = activities;
_condition = condition;
Expand Down Expand Up @@ -72,11 +78,17 @@ public class ConditionalActivityBinder<TInstance, TData> :
where TInstance : class
{
readonly EventActivities<TInstance> _activities;
readonly StateMachineCondition<TInstance, TData> _condition;
readonly StateMachineAsyncCondition<TInstance, TData> _condition;
readonly Event _event;

public ConditionalActivityBinder(Event @event, StateMachineCondition<TInstance, TData> condition,
EventActivities<TInstance> activities)
: this(@event, context => Task.FromResult(condition(context)), activities)
{
}

public ConditionalActivityBinder(Event @event, StateMachineAsyncCondition<TInstance, TData> condition,
EventActivities<TInstance> activities)
{
_activities = activities;
_condition = condition;
Expand Down
17 changes: 14 additions & 3 deletions src/Automatonymous/Binders/ConditionalExceptionActivityBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace Automatonymous.Binders
{
using System;
using System.Threading.Tasks;
using Activities;
using Behaviors;

Expand All @@ -23,10 +24,15 @@ public class ConditionalExceptionActivityBinder<TInstance, TException> :
where TException : Exception
{
readonly EventActivities<TInstance> _activities;
readonly StateMachineExceptionCondition<TInstance, TException> _condition;
readonly StateMachineAsyncExceptionCondition<TInstance, TException> _condition;
readonly Event _event;

public ConditionalExceptionActivityBinder(Event @event, StateMachineExceptionCondition<TInstance, TException> condition, EventActivities<TInstance> activities)
:this(@event, context => Task.FromResult(condition(context)), activities)
{
}

public ConditionalExceptionActivityBinder(Event @event, StateMachineAsyncExceptionCondition<TInstance, TException> condition, EventActivities<TInstance> activities)
{
_activities = activities;
_condition = condition;
Expand Down Expand Up @@ -75,10 +81,15 @@ public class ConditionalExceptionActivityBinder<TInstance, TData, TException> :
where TException : Exception
{
readonly EventActivities<TInstance> _activities;
readonly StateMachineExceptionCondition<TInstance, TData, TException> _condition;
readonly StateMachineAsyncExceptionCondition<TInstance, TData, TException> _condition;
readonly Event _event;

public ConditionalExceptionActivityBinder(Event @event, StateMachineExceptionCondition<TInstance, TData, TException> condition,
public ConditionalExceptionActivityBinder(Event @event, StateMachineExceptionCondition<TInstance, TData, TException> condition, EventActivities<TInstance> activities)
: this(@event, context => Task.FromResult(condition(context)), activities)
{
}

public ConditionalExceptionActivityBinder(Event @event, StateMachineAsyncExceptionCondition<TInstance, TData, TException> condition,
EventActivities<TInstance> activities)
{
_activities = activities;
Expand Down
Loading

0 comments on commit b1c666a

Please sign in to comment.