-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Feat: Add Action * docs: fix documentation * Fix: Remove tests and mocks for sonar * feat: add actionable to action * Test: Add Tests for Action * fix: conform to Jens * refactor: add constructor * feat: Add the ability to not have a query/guard * fix: make constructor public * fix: don't let the build crash because of the tests * fix: Change visibility to internal * chore: simplify tests
- Loading branch information
1 parent
c34f258
commit 8ed6556
Showing
6 changed files
with
262 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
|
||
namespace Aplib.Core | ||
{ | ||
/// <summary> | ||
/// Describes an action that can be executed and guarded. | ||
/// </summary> | ||
public class Action | ||
{ | ||
/// <summary> | ||
/// Gets or sets the effect of the action. | ||
/// </summary> | ||
protected System.Action Effect { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the guard of the action. | ||
/// </summary> | ||
protected Func<bool> Guard { get; set; } = () => true; | ||
|
||
/// <summary> | ||
/// Initializes a new empty instance of the <see cref="Action{TQuery}"/> class. | ||
/// </summary> | ||
/// <remarks>Only meant for internal use</remarks> | ||
protected internal Action() | ||
{ | ||
Effect = () => { }; | ||
Guard = () => false; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Action{TQuery}"/> class. | ||
/// </summary> | ||
/// <param name="effect">The effect of the action.</param> | ||
public Action(System.Action effect) => Effect = effect; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Action{TQuery}"/> class. | ||
/// </summary> | ||
/// <param name="effect">The effect of the action.</param> | ||
/// <param name="guard">The guard of the action.</param> | ||
public Action(System.Action effect, Func<bool> guard) : this(effect) => Guard = guard; | ||
|
||
/// <summary> | ||
/// Execute the action against the world. | ||
/// </summary> | ||
internal virtual void Execute() => Effect(); | ||
|
||
/// <summary> | ||
/// Guard the action against unwanted execution. The result is stored and can be used in the effect. | ||
/// </summary> | ||
internal virtual bool IsActionable() => Guard(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
|
||
namespace Aplib.Core | ||
{ | ||
/// <summary> | ||
/// Describes an action that can be executed and guarded with a query that stores the result of the guard. | ||
/// The result can be used in the effect. | ||
/// </summary> | ||
/// <typeparam name="TQuery">The type of the query of the action</typeparam> | ||
public class GuardedAction<TQuery> : Action | ||
{ | ||
/// <summary> | ||
/// Gets or sets the result of the guard. | ||
/// </summary> | ||
protected TQuery? StoredGuardResult { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the effect of the action. | ||
/// </summary> | ||
protected new System.Action<TQuery> Effect { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the guard of the action. | ||
/// </summary> | ||
protected new Func<TQuery?> Guard { get; set; } | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="GuardedAction{TQuery}"/> class. | ||
/// </summary> | ||
/// <param name="effect">The effect of the action.</param> | ||
/// <param name="guard">The guard of the action.</param> | ||
public GuardedAction(System.Action<TQuery> effect, Func<TQuery?> guard) : base() | ||
{ | ||
Effect = effect; | ||
Guard = guard; | ||
} | ||
|
||
/// <inheritdoc/> | ||
internal override void Execute() => Effect(StoredGuardResult!); | ||
|
||
/// <inheritdoc/> | ||
internal override bool IsActionable() | ||
{ | ||
StoredGuardResult = Guard(); | ||
return StoredGuardResult is not null; | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
using Aplib.Core; | ||
using Action = Aplib.Core.Action; | ||
|
||
namespace Aplib.Tests.Core; | ||
|
||
/// <summary> | ||
/// Describes a set of tests for the <see cref="GuardedAction{TQuery}"/> class. | ||
/// </summary> | ||
public class ActionTests | ||
{ | ||
/// <summary> | ||
/// Given a side effect action with a string guard, | ||
/// When the action is executed, | ||
/// Then the result should be null. | ||
/// </summary> | ||
[Fact] | ||
public void Execute_SideEffects_ReturnsCorrectEffect() | ||
{ | ||
// Arrange | ||
string? result = "abc"; | ||
Action action = new(effect: () => result = "def"); | ||
|
||
// Act | ||
action.Execute(); | ||
|
||
// Assert | ||
Assert.Equal("def", result); | ||
} | ||
|
||
/// <summary> | ||
/// Given an action with no query, | ||
/// When checking if the action is actionable, | ||
/// Then the result should always be true. | ||
/// </summary> | ||
[Fact] | ||
public void IsActionable_NoQuery_AlwaysTrue() | ||
{ | ||
// Arrange | ||
Action action = new(effect: () => { }); | ||
|
||
// Act | ||
bool actionable = action.IsActionable(); | ||
|
||
// Assert | ||
Assert.True(actionable); | ||
} | ||
|
||
/// <summary> | ||
/// Given an action with a true query, | ||
/// When checking if the action is actionable, | ||
/// Then the result should be true. | ||
/// </summary> | ||
[Fact] | ||
public void IsActionable_QueryWithTrue_ReturnsTrue() | ||
{ | ||
// Arrange | ||
Action action = new(effect: () => { }, guard: () => true); | ||
|
||
// Act | ||
bool actionable = action.IsActionable(); | ||
|
||
// Assert | ||
Assert.True(actionable); | ||
} | ||
|
||
/// <summary> | ||
/// Given an action with a false query, | ||
/// When checking if the action is actionable, | ||
/// Then the result should be false. | ||
/// </summary> | ||
[Fact] | ||
public void IsActionable_QueryWithFalse_ReturnsFalse() | ||
{ | ||
// Arrange | ||
Action action = new(effect: () => { }, guard: () => false); | ||
|
||
// Act | ||
bool actionable = action.IsActionable(); | ||
|
||
// Assert | ||
Assert.False(actionable); | ||
} | ||
|
||
/// <summary> | ||
/// Given a guarded action with an int guard, | ||
/// When the action is guarded and executed, | ||
/// Then the result should be the value of the guard. | ||
/// </summary> | ||
[Fact] | ||
public void Execute_WithGuard_ShouldInvokeQueryAndStoreResult() | ||
{ | ||
// Arrange | ||
int result = 0; | ||
GuardedAction<int> action = new(guard: () => 42, effect: (guard) => result = guard); | ||
|
||
// Act | ||
_ = action.IsActionable(); | ||
action.Execute(); | ||
|
||
// Assert | ||
Assert.Equal(42, result); | ||
} | ||
|
||
/// <summary> | ||
/// Given an action with a non-null int guard, | ||
/// When checking if the action is actionable, | ||
/// Then the result should be true. | ||
/// </summary> | ||
[Fact] | ||
public void IsActionable_QueryIsNotNull_IsActionable() | ||
{ | ||
// Arrange | ||
GuardedAction<int> action = new(guard: () => 10, effect: b => { }); | ||
|
||
// Act | ||
bool result = action.IsActionable(); | ||
|
||
// Assert | ||
Assert.True(result); | ||
} | ||
|
||
/// <summary> | ||
/// Given an action with a false bool guard, | ||
/// When checking if the action is actionable, | ||
/// Then the result should be true. | ||
/// </summary> | ||
[Fact] | ||
public void IsActionable_QueryIsFalse_IsActionable() | ||
{ | ||
// Arrange | ||
GuardedAction<bool> action = new(guard: () => false, effect: b => { }); | ||
|
||
// Act | ||
bool result = action.IsActionable(); | ||
|
||
// Assert | ||
Assert.True(result); | ||
} | ||
|
||
/// <summary> | ||
/// Given an action with a null object guard, | ||
/// When checking if the action is actionable, | ||
/// Then the result should be false. | ||
/// </summary> | ||
[Fact] | ||
public void IsActionable_QueryIsNull_IsNotActionable() | ||
{ | ||
// Arrange | ||
GuardedAction<object> action = new(guard: () => null!, effect: b => { }); | ||
|
||
// Act | ||
bool result = action.IsActionable(); | ||
|
||
// Assert | ||
Assert.False(result); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.