Skip to content

Commit

Permalink
Merge pull request #582 from marcinjahn/allocation-free-result-mapif
Browse files Browse the repository at this point in the history
feat: add allocation-free overloads for Result.Map and Result.MapIf
  • Loading branch information
vkhorikov authored Dec 23, 2024
2 parents b6ca7d1 + b4b398c commit 7a6e26f
Show file tree
Hide file tree
Showing 30 changed files with 3,086 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ protected MapIfTestsBase()
predicateExecuted = false;
}

protected Func<T, T> GetAction() => value =>
{
actionExecuted.Should().BeFalse();
value.Should().Be(T.Value);
protected Func<T, T> GetAction() =>
value =>
{
actionExecuted.Should().BeFalse();
value.Should().Be(T.Value);

actionExecuted = true;
return T.Value2;
};
actionExecuted = true;
return T.Value2;
};

protected Func<T, Task<T>> GetTaskAction()
{
Expand Down Expand Up @@ -69,5 +70,7 @@ protected static Result<T, E> GetExpectedValueErrorResult(bool isSuccess, bool c

return Result.SuccessIf(isSuccess, T.Value2, E.Value2);
}

protected readonly string ContextMessage = "Context data";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ public class MapIfTests_Task_Left : MapIfTestsBase
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_T_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
public async Task MapIf_Task_Left_T_executes_func_conditionally_and_returns_new_result(
bool isSuccess,
bool condition
)
{
Result<T> result = Result.SuccessIf(isSuccess, T.Value, ErrorMessage);
Task<Result<T>> resultTask = Result
.SuccessIf(isSuccess, T.Value, ErrorMessage)
.AsTask();

Result<T> returned = await result.MapIf(condition, GetTaskAction());
Result<T> returned = await resultTask.MapIf(condition, GetAction());

actionExecuted.Should().Be(isSuccess && condition);
returned.Should().Be(GetExpectedValueResult(isSuccess, condition));
Expand All @@ -26,11 +31,14 @@ public async Task MapIf_Task_Left_T_executes_func_conditionally_and_returns_new_
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_T_E_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
public async Task MapIf_Task_Left_T_E_executes_func_conditionally_and_returns_new_result(
bool isSuccess,
bool condition
)
{
Result<T, E> result = Result.SuccessIf(isSuccess, T.Value, E.Value);
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();

Result<T, E> returned = await result.MapIf(condition, GetTaskAction());
Result<T, E> returned = await resultTask.MapIf(condition, GetAction());

actionExecuted.Should().Be(isSuccess && condition);
returned.Should().Be(GetExpectedValueErrorResult(isSuccess, condition));
Expand All @@ -41,11 +49,16 @@ public async Task MapIf_Task_Left_T_E_executes_func_conditionally_and_returns_ne
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_computes_predicate_T_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
public async Task MapIf_Task_Left_computes_predicate_T_executes_func_conditionally_and_returns_new_result(
bool isSuccess,
bool condition
)
{
Result<T> result = Result.SuccessIf(isSuccess, T.Value, ErrorMessage);
Task<Result<T>> resultTask = Result
.SuccessIf(isSuccess, T.Value, ErrorMessage)
.AsTask();

Result<T> returned = await result.MapIf(GetValuePredicate(condition), GetTaskAction());
Result<T> returned = await resultTask.MapIf(GetValuePredicate(condition), GetAction());

predicateExecuted.Should().Be(isSuccess);
actionExecuted.Should().Be(isSuccess && condition);
Expand All @@ -57,11 +70,135 @@ public async Task MapIf_Task_Left_computes_predicate_T_executes_func_conditional
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_computes_predicate_T_E_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
public async Task MapIf_Task_Left_computes_predicate_T_E_executes_func_conditionally_and_returns_new_result(
bool isSuccess,
bool condition
)
{
Result<T, E> result = Result.SuccessIf(isSuccess, T.Value, E.Value);
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();

Result<T, E> returned = await result.MapIf(GetValuePredicate(condition), GetTaskAction());
Result<T, E> returned = await resultTask.MapIf(
GetValuePredicate(condition),
GetAction()
);

predicateExecuted.Should().Be(isSuccess);
actionExecuted.Should().Be(isSuccess && condition);
returned.Should().Be(GetExpectedValueErrorResult(isSuccess, condition));
}

[Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_T_with_context_executes_func_conditionally_and_passes_context(
bool isSuccess,
bool condition
)
{
Task<Result<T>> resultTask = Result
.SuccessIf(isSuccess, T.Value, ErrorMessage)
.AsTask();

Result<T> returned = await resultTask.MapIf(
condition,
(value, context) =>
{
context.Should().Be(ContextMessage);
return GetAction()(value);
},
ContextMessage
);

actionExecuted.Should().Be(isSuccess && condition);
returned.Should().Be(GetExpectedValueResult(isSuccess, condition));
}

[Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_T_E_with_context_executes_func_conditionally_and_passes_context(
bool isSuccess,
bool condition
)
{
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();

Result<T, E> returned = await resultTask.MapIf(
condition,
(value, context) =>
{
context.Should().Be(ContextMessage);
return GetAction()(value);
},
ContextMessage
);

actionExecuted.Should().Be(isSuccess && condition);
returned.Should().Be(GetExpectedValueErrorResult(isSuccess, condition));
}

[Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_computes_predicate_T_with_context_executes_func_conditionally_and_passes_context(
bool isSuccess,
bool condition
)
{
Task<Result<T>> resultTask = Result
.SuccessIf(isSuccess, T.Value, ErrorMessage)
.AsTask();

Result<T> returned = await resultTask.MapIf(
(value, context) =>
{
context.Should().Be(ContextMessage);
return GetValuePredicate(condition)(value);
},
(value, context) =>
{
context.Should().Be(ContextMessage);
return GetAction()(value);
},
ContextMessage
);

predicateExecuted.Should().Be(isSuccess);
actionExecuted.Should().Be(isSuccess && condition);
returned.Should().Be(GetExpectedValueResult(isSuccess, condition));
}

[Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task MapIf_Task_Left_computes_predicate_T_E_with_context_executes_func_conditionally_and_passes_context(
bool isSuccess,
bool condition
)
{
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();

Result<T, E> returned = await resultTask.MapIf(
(value, context) =>
{
context.Should().Be(ContextMessage);
return GetValuePredicate(condition)(value);
},
(value, context) =>
{
context.Should().Be(ContextMessage);
return GetAction()(value);
},
ContextMessage
);

predicateExecuted.Should().Be(isSuccess);
actionExecuted.Should().Be(isSuccess && condition);
Expand Down
Loading

0 comments on commit 7a6e26f

Please sign in to comment.