Skip to content

Commit

Permalink
Merge pull request #130 from xodial/xodial/on-start-stop
Browse files Browse the repository at this point in the history
feat: add OnStart/OnStop to LogicBlock
  • Loading branch information
jolexxa authored Jan 23, 2025
2 parents e6fcbbe + 1a44a6e commit 3d5544f
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 10 deletions.
8 changes: 8 additions & 0 deletions Chickensoft.LogicBlocks.Tests/test/fixtures/FakeLogicBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ public static class Output {
public partial class FakeLogicBlock : LogicBlock<FakeLogicBlock.State> {
public Func<Transition>? InitialState { get; set; }

public Action? OnStartCalled { get; set; }

public Action? OnStopCalled { get; set; }

public List<Exception> Exceptions { get; } = new();

public override Transition GetInitialState() =>
Expand All @@ -167,6 +171,10 @@ public FakeLogicBlock(Action<Exception>? onError = null) {
_onError = onError;
}

public override void OnStart() => OnStartCalled?.Invoke();

public override void OnStop() => OnStopCalled?.Invoke();

~FakeLogicBlock() { }

protected override void HandleError(Exception e) {
Expand Down
31 changes: 28 additions & 3 deletions Chickensoft.LogicBlocks.Tests/test/src/LogicBlockTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -327,20 +327,24 @@ public void StartsManuallyAndIgnoresStartWhenProcessing() {
[Fact]
public void StartEntersState() {
var enterCalled = false;
var onStartCalled = false;
var context = new FakeContext();
var block = new FakeLogicBlock() {
InitialState = () =>
new FakeLogicBlock.Transition(new FakeLogicBlock.State.OnEnterState() {
Callback = (previous) => enterCalled = true
})
}),
OnStartCalled = () => onStartCalled = true
};

enterCalled.ShouldBeFalse();
onStartCalled.ShouldBeFalse();

block.Start();
block.Start(); // Should do nothing.

enterCalled.ShouldBeTrue();
onStartCalled.ShouldBeTrue();
}

[Fact]
Expand All @@ -357,31 +361,50 @@ public void StartDoesNothingIfProcessing() {
logic.Value.ShouldBeOfType<FakeLogicBlock.State.StateA>();
}

[Fact]
public void ImplicitStartCallsOnStart() {
var onStartCalled = false;
var logic = new FakeLogicBlock() {
OnStartCalled = () => onStartCalled = true
};

logic.Input(new FakeLogicBlock.Input.InputOne(2, 3));

onStartCalled.ShouldBeTrue();
}

[Fact]
public void StopExitsState() {
var exitCalled = false;
var onStopCalled = false;
var context = new FakeContext();
var block = new FakeLogicBlock() {
InitialState = () => new FakeLogicBlock.Transition(
new FakeLogicBlock.State.OnExitState() {
Callback = (previous) => exitCalled = true
}
)
),
OnStopCalled = () => onStopCalled = true
};

exitCalled.ShouldBeFalse();
onStopCalled.ShouldBeFalse();

block.Start();
block.Stop();
block.Stop(); // Should do nothing.

exitCalled.ShouldBeTrue();
onStopCalled.ShouldBeTrue();
}

[Fact]
public void StopDoesNothingIfProcessing() {
var onStopCalled = false;
var context = new FakeContext();
var logic = new FakeLogicBlock();
var logic = new FakeLogicBlock() {
OnStopCalled = () => onStopCalled = true
};
logic.InitialState = () => new FakeLogicBlock.Transition(
new FakeLogicBlock.State.OnExitState() {
Callback = (previous) => logic.Stop()
Expand All @@ -390,6 +413,8 @@ public void StopDoesNothingIfProcessing() {

logic.Input(new FakeLogicBlock.Input.InputOne(2, 3));
logic.IsStarted.ShouldBeTrue();

onStopCalled.ShouldBeFalse();
}

[Fact]
Expand Down
24 changes: 17 additions & 7 deletions Chickensoft.LogicBlocks/src/LogicBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,18 @@ public void Start() {
Flush();
}

/// <summary>
/// Called when the logic block is started. Override this method to
/// perform any initialization logic.
/// </summary>
public virtual void OnStart() { }

/// <inheritdoc />
public void Stop() {
if (IsProcessing || _value is null) { return; }

OnStop();

// Repeatedly exit and detach the current state until there is none.
ChangeState(null);

Expand All @@ -239,6 +247,12 @@ public void Stop() {
_value = null;
}

/// <summary>
/// Called when the logic block is stopped. Override this method to
/// perform any cleanup logic.
/// </summary>
public virtual void OnStop() { }

/// <inheritdoc />
public TState ForceReset(TState state) {
if (IsProcessing) {
Expand Down Expand Up @@ -386,6 +400,8 @@ internal TState ProcessInputs<TInputType>(

if (_value is null) {
// No state yet. Let's get the first state going!
OnStart();
Blackboard.InstantiateAnyMissingSavedData();
ChangeState(RestoredState as TState ?? GetInitialState().State);
RestoredState = null;
}
Expand Down Expand Up @@ -500,13 +516,7 @@ TState fallback
/// </summary>
/// <returns>The resting state.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private TState Flush() {
if (_value is null) {
Blackboard.InstantiateAnyMissingSavedData();
}

return ProcessInputs<int>();
}
private TState Flush() => ProcessInputs<int>();

/// <summary>
/// Determines if two logic blocks are equivalent. Logic blocks are equivalent
Expand Down

0 comments on commit 3d5544f

Please sign in to comment.