Skip to content

Commit

Permalink
Merge pull request #532 from mclift/bugfix/OnEntryFromAsync-InvalidOp…
Browse files Browse the repository at this point in the history
…erationException

Bugfix: execute OnEntryFromAsync actions from FireAsync
  • Loading branch information
mclift authored Jul 4, 2023
2 parents 22e29cd + 5bcedd6 commit b45b999
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/Stateless/EntryActionBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,18 @@ public AsyncFrom(TTriggerType trigger, Func<Transition, object[], Task> action,
public override void Execute(Transition transition, object[] args)
{
if (transition.Trigger.Equals(Trigger))
{
base.Execute(transition, args);
}
}

public override Task ExecuteAsync(Transition transition, object[] args)
{
Execute(transition, args);
if (transition.Trigger.Equals(Trigger))
{
return base.ExecuteAsync(transition, args);
}

return TaskResult.Done;
}
}
Expand Down
68 changes: 68 additions & 0 deletions test/Stateless.Tests/AsyncActionsFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,74 @@ public void VerifyNotEnterSuperstateWhenDoingInitialTransition()

Assert.Equal(State.D, sm.State);
}

[Fact]
public void OnEntryFromAsync_WhenTriggeredSynchronously_Throws()
{
var sm = new StateMachine<State, Trigger>(State.A);

sm.Configure(State.A).Permit(Trigger.X, State.B);

sm.Configure(State.B)
.OnEntryFromAsync(Trigger.X, async () => await Task.Run(() => { }));

Assert.Throws<InvalidOperationException>(() => sm.Fire(Trigger.X));
}

[Fact]
public async Task OnEntryFromAsync_WhenTriggered_InvokesAction()
{
bool wasInvoked = false;

var sm = new StateMachine<State, Trigger>(State.A);

sm.Configure(State.A).Permit(Trigger.X, State.B);

sm.Configure(State.B)
.OnEntryFromAsync(Trigger.X, async () => await Task.Run(() => { wasInvoked = true; }));

await sm.FireAsync(Trigger.X);

Assert.True(wasInvoked);
}

[Fact]
public void OnEntryFromAsync_WhenEnteringByAnotherTriggerSynchronously_DoesNotThrow()
{
bool wasInvoked = false;

var sm = new StateMachine<State, Trigger>(State.A);

sm.Configure(State.A)
.Permit(Trigger.X, State.B)
.Permit(Trigger.Y, State.B);

sm.Configure(State.B)
.OnEntryFromAsync(Trigger.X, async () => await Task.Run(() => { wasInvoked = true; }));

sm.Fire(Trigger.Y);

Assert.False(wasInvoked);
}

[Fact]
public async Task OnEntryFromAsync_WhenEnteringByAnotherTrigger_InvokesAction()
{
bool wasInvoked = false;

var sm = new StateMachine<State, Trigger>(State.A);

sm.Configure(State.A)
.Permit(Trigger.X, State.B)
.Permit(Trigger.Y, State.B);

sm.Configure(State.B)
.OnEntryFromAsync(Trigger.X, async () => await Task.Run(() => { wasInvoked = true; }));

await sm.FireAsync(Trigger.Y);

Assert.False(wasInvoked);
}
}
}

Expand Down

0 comments on commit b45b999

Please sign in to comment.