Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions TUnit.Assertions.Tests/Bugs/Tests3137.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using TUnit.Assertions.AssertConditions;

namespace TUnit.Assertions.Tests.Bugs;

public class Tests3137
{
[Test]
public async Task AssertOnAsyncLambdaIsNotEvaluatedToEarly()
{
int count = 0;
await Assert.That(() =>
{
count++;
return Task.CompletedTask;
}).RegisterAssertion(new TestAssertCondition(() => count, expectedIncrement: 1), []);
}

private class TestAssertCondition(Func<int> getCount, int expectedIncrement) : DelegateAssertCondition
{
private readonly int _before = getCount();

protected override ValueTask<AssertionResult> GetResult(
object? actualValue,
Exception? exception,
AssertionMetadata assertionMetadata)
{
var after = getCount();
var actualIncrement = after - _before;
return AssertionResult.FailIf(
actualIncrement != expectedIncrement,
$"Actual increment was {actualIncrement} but expected {expectedIncrement}.");

// silence Codacy
_ = actualValue;
_ = exception;
_ = assertionMetadata;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Text;
using TUnit.Assertions.Assertions.Generics.Conditions;
using TUnit.Assertions.Extensions;

namespace TUnit.Assertions.AssertConditions.Interfaces;

Expand All @@ -12,13 +11,13 @@ public ConvertedDelegateSource(IDelegateSource source)

ActualExpression = source.ActualExpression;
Assertions = new Stack<BaseAssertCondition>([new DelegateConversionAssertionCondition<TToType>(source, (BaseAssertCondition<object?>) source.Assertions.Peek())]);
AssertionDataTask = ConvertAsync(source, convertToAssertCondition);
LazyAssertionData = source.LazyAssertionData.WithExceptionAsValue(source, convertToAssertCondition);
ExpressionBuilder = source.ExpressionBuilder;
}

public string? ActualExpression { get; }
public Stack<BaseAssertCondition> Assertions { get; }
public ValueTask<AssertionData> AssertionDataTask { get; }
public LazyAssertionData LazyAssertionData { get; }

public StringBuilder ExpressionBuilder { get; }

Expand All @@ -38,13 +37,4 @@ public ISource WithAssertion(BaseAssertCondition assertCondition)
Assertions.Push(assertCondition);
return this;
}

private static async ValueTask<AssertionData> ConvertAsync(IDelegateSource delegateSource, ConvertExceptionToValueAssertCondition<TToType> convertToAssertCondition)
{
var invokableAssertionBuilder = delegateSource.RegisterAssertion(convertToAssertCondition, [], null);

return await invokableAssertionBuilder.ProcessAssertionsAsync(assertionData =>
Task.FromResult(assertionData with { Result = convertToAssertCondition.ConvertedExceptionValue, Exception = null, End = DateTimeOffset.Now }));

}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Text;
using TUnit.Assertions.Assertions.Generics.Conditions;
using TUnit.Assertions.Extensions;

namespace TUnit.Assertions.AssertConditions.Interfaces;

Expand All @@ -10,13 +9,13 @@ public ConvertedValueSource(IValueSource<TFromType> source, ConvertToAssertCondi
{
ActualExpression = source.ActualExpression;
Assertions = new Stack<BaseAssertCondition>([new ValueConversionAssertionCondition<TFromType, TToType>(source, convertToAssertCondition)]);
AssertionDataTask = ConvertAsync(source, convertToAssertCondition);
LazyAssertionData = source.LazyAssertionData.WithConversion(source, convertToAssertCondition);
ExpressionBuilder = source.ExpressionBuilder;
}

public string? ActualExpression { get; }
public Stack<BaseAssertCondition> Assertions { get; }
public ValueTask<AssertionData> AssertionDataTask { get; }
public LazyAssertionData LazyAssertionData { get; }

public StringBuilder ExpressionBuilder { get; }

Expand All @@ -36,13 +35,4 @@ public ISource WithAssertion(BaseAssertCondition assertCondition)
Assertions.Push(assertCondition);
return this;
}

private static async ValueTask<AssertionData> ConvertAsync(IValueSource<TFromType> valueSource, ConvertToAssertCondition<TFromType, TToType> convertToAssertCondition)
{
var invokableAssertionBuilder = valueSource.RegisterAssertion(convertToAssertCondition, [], null);

return await invokableAssertionBuilder.ProcessAssertionsAsync(assertionData =>
Task.FromResult(assertionData with { Result = convertToAssertCondition.ConvertedValue, End = DateTimeOffset.Now }));

}
}
2 changes: 1 addition & 1 deletion TUnit.Assertions/AssertConditions/Interfaces/ISource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public interface ISource
{
string? ActualExpression { get; }
internal Stack<BaseAssertCondition> Assertions { get; }
internal ValueTask<AssertionData> AssertionDataTask { get; }
internal LazyAssertionData LazyAssertionData { get; }
internal StringBuilder ExpressionBuilder { get; }

ISource AppendExpression(string expression);
Expand Down
2 changes: 1 addition & 1 deletion TUnit.Assertions/AssertConditions/Operators/DelegateAnd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static DelegateAnd<TActual> Create(AssertionBuilder assertionBuilder)
string? ISource.ActualExpression => ((ISource) assertionBuilder).ActualExpression;

Stack<BaseAssertCondition> ISource.Assertions => ((ISource) assertionBuilder).Assertions;
ValueTask<AssertionData> ISource.AssertionDataTask => ((ISource) assertionBuilder).AssertionDataTask;
LazyAssertionData ISource.LazyAssertionData => ((ISource) assertionBuilder).LazyAssertionData;
StringBuilder ISource.ExpressionBuilder => ((ISource) assertionBuilder).ExpressionBuilder;

ISource ISource.AppendExpression(string expression)
Expand Down
2 changes: 1 addition & 1 deletion TUnit.Assertions/AssertConditions/Operators/DelegateOr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static DelegateOr<TActual> Create(AssertionBuilder assertionBuilder)
string? ISource.ActualExpression => ((ISource) assertionBuilder).ActualExpression;

Stack<BaseAssertCondition> ISource.Assertions => ((ISource) assertionBuilder).Assertions;
ValueTask<AssertionData> ISource.AssertionDataTask => ((ISource) assertionBuilder).AssertionDataTask;
LazyAssertionData ISource.LazyAssertionData => ((ISource) assertionBuilder).LazyAssertionData;
StringBuilder ISource.ExpressionBuilder => ((ISource) assertionBuilder).ExpressionBuilder;

ISource ISource.AppendExpression(string expression)
Expand Down
2 changes: 1 addition & 1 deletion TUnit.Assertions/AssertConditions/Operators/ValueAnd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static ValueAnd<TActual> Create(AssertionBuilder assertionBuilder)
}

Stack<BaseAssertCondition> ISource.Assertions => ((ISource) assertionBuilder).Assertions;
ValueTask<AssertionData> ISource.AssertionDataTask => ((ISource) assertionBuilder).AssertionDataTask;
LazyAssertionData ISource.LazyAssertionData => ((ISource) assertionBuilder).LazyAssertionData;
StringBuilder ISource.ExpressionBuilder => ((ISource) assertionBuilder).ExpressionBuilder;
string? ISource.ActualExpression => ((ISource) assertionBuilder).ActualExpression;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static ValueDelegateAnd<TActual> Create(AssertionBuilder assertionBuilder
string? ISource.ActualExpression => ((ISource) assertionBuilder).ActualExpression;

Stack<BaseAssertCondition> ISource.Assertions => ((ISource) assertionBuilder).Assertions;
ValueTask<AssertionData> ISource.AssertionDataTask => ((ISource) assertionBuilder).AssertionDataTask;
LazyAssertionData ISource.LazyAssertionData => ((ISource) assertionBuilder).LazyAssertionData;
StringBuilder ISource.ExpressionBuilder => ((ISource) assertionBuilder).ExpressionBuilder;

ISource ISource.AppendExpression(string expression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static ValueDelegateOr<TActual> Create(AssertionBuilder assertionBuilder)
string? ISource.ActualExpression => ((ISource) assertionBuilder).ActualExpression;

Stack<BaseAssertCondition> ISource.Assertions => ((ISource) assertionBuilder).Assertions;
ValueTask<AssertionData> ISource.AssertionDataTask => ((ISource) assertionBuilder).AssertionDataTask;
LazyAssertionData ISource.LazyAssertionData => ((ISource) assertionBuilder).LazyAssertionData;
StringBuilder ISource.ExpressionBuilder => ((ISource) assertionBuilder).ExpressionBuilder;

ISource ISource.AppendExpression(string expression)
Expand Down
2 changes: 1 addition & 1 deletion TUnit.Assertions/AssertConditions/Operators/ValueOr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ValueOr<TActual>(AssertionBuilder assertionBuilder) : IValueSource<
string? ISource.ActualExpression => ((ISource) assertionBuilder).ActualExpression;

Stack<BaseAssertCondition> ISource.Assertions => ((ISource) assertionBuilder).Assertions;
ValueTask<AssertionData> ISource.AssertionDataTask => ((ISource) assertionBuilder).AssertionDataTask;
LazyAssertionData ISource.LazyAssertionData => ((ISource) assertionBuilder).LazyAssertionData;
StringBuilder ISource.ExpressionBuilder => ((ISource) assertionBuilder).ExpressionBuilder;

ISource ISource.AppendExpression(string expression)
Expand Down
2 changes: 1 addition & 1 deletion TUnit.Assertions/AssertionBuilders/AndAssertionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertionBuilders;

public class AndAssertionBuilder : AssertionBuilder, IAndAssertionBuilder
{
internal AndAssertionBuilder(AssertionBuilder assertionBuilder) : base(((ISource) assertionBuilder).AssertionDataTask, (
internal AndAssertionBuilder(AssertionBuilder assertionBuilder) : base(((ISource) assertionBuilder).LazyAssertionData, (
(ISource) assertionBuilder).ActualExpression!, (
(ISource) assertionBuilder).ExpressionBuilder, ((ISource) assertionBuilder).Assertions)
{
Expand Down
26 changes: 13 additions & 13 deletions TUnit.Assertions/AssertionBuilders/AssertionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ public abstract class AssertionBuilder : ISource

public AssertionBuilder(ISource source)
{
_assertionDataTask = source.AssertionDataTask;
_lazyAssertionData = source.LazyAssertionData;
_actualExpression = source.ActualExpression;
_expressionBuilder = source.ExpressionBuilder;
_assertions = source.Assertions;
}

public AssertionBuilder(ValueTask<AssertionData> assertionDataTask, string actualExpression, StringBuilder expressionBuilder, Stack<BaseAssertCondition> assertions)
public AssertionBuilder(LazyAssertionData lazyAssertionData, string actualExpression, StringBuilder expressionBuilder, Stack<BaseAssertCondition> assertions)
{
_assertionDataTask = assertionDataTask;
_lazyAssertionData= lazyAssertionData;
_actualExpression = actualExpression;
_expressionBuilder = expressionBuilder;
_assertions = assertions;
}

public AssertionBuilder(ValueTask<AssertionData> assertionDataTask, string? actualExpression)
public AssertionBuilder(LazyAssertionData lazyAssertionData, string? actualExpression)
{
_assertionDataTask = assertionDataTask;
_lazyAssertionData= lazyAssertionData;
_actualExpression = actualExpression;

if (string.IsNullOrEmpty(actualExpression))
Expand All @@ -55,13 +55,13 @@ public AssertionBuilder(ValueTask<AssertionData> assertionDataTask, string? actu

string? ISource.ActualExpression => _actualExpression;

ValueTask<AssertionData> ISource.AssertionDataTask => _assertionDataTask;
LazyAssertionData ISource.LazyAssertionData => _lazyAssertionData;

Stack<BaseAssertCondition> ISource.Assertions => _assertions;

protected readonly List<AssertionResult> Results = [];
private readonly StringBuilder _expressionBuilder;
private readonly ValueTask<AssertionData> _assertionDataTask;
private readonly LazyAssertionData _lazyAssertionData;
private readonly Stack<BaseAssertCondition> _assertions = new();
private readonly string? _actualExpression;

Expand Down Expand Up @@ -157,9 +157,9 @@ internal async Task<AssertionData> ProcessAssertionsAsync()
var exception = new AssertionException(
$"""
Expected {assertion.Subject} {assertion.GetExpectationWithReason()}

but {result.Message}

at {((IInvokableAssertionBuilder) this).GetExpression()}
"""
);
Expand All @@ -179,16 +179,16 @@ internal async Task<AssertionData> ProcessAssertionsAsync()

private async Task<AssertionData> GetAssertionData()
{
var minimumWait = _assertions.Select(x => x.WaitFor).Min();
var timeout = _assertions.Select(x => x.WaitFor).Min();

if (minimumWait is null)
if (timeout is null)
{
return await _assertionDataTask;
return await _lazyAssertionData.GetResultAsync();
}

using var cts = new CancellationTokenSource();

var completedTask = await Task.WhenAny(_assertionDataTask.AsTask(), GetMinimumWaitTask(minimumWait.Value, cts.Token));
var completedTask = await Task.WhenAny(_lazyAssertionData.GetResultAsync().AsTask(), GetMinimumWaitTask(timeout.Value, cts.Token));

cts.Cancel();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class AsyncDelegateAssertionBuilder
: AssertionBuilder,
IDelegateSource
{
internal AsyncDelegateAssertionBuilder(Func<Task> function, string? expressionBuilder) : base(function.AsAssertionData(expressionBuilder), expressionBuilder)
internal AsyncDelegateAssertionBuilder(Func<Task> function, string? expressionBuilder) : base(LazyAssertionData.Create(function, expressionBuilder), expressionBuilder)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertionBuilders;
public class AsyncValueDelegateAssertionBuilder<TActual>
: AssertionBuilder, IValueDelegateSource<TActual>
{
internal AsyncValueDelegateAssertionBuilder(Func<Task<TActual>> function, string? expressionBuilder) : base(function.AsAssertionData(expressionBuilder), expressionBuilder)
internal AsyncValueDelegateAssertionBuilder(Func<Task<TActual>> function, string? expressionBuilder) : base(LazyAssertionData.Create(function, expressionBuilder), expressionBuilder)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class DelegateAssertionBuilder
: AssertionBuilder,
IDelegateSource
{
internal DelegateAssertionBuilder(Action action, string? expressionBuilder) : base(action.AsAssertionData(expressionBuilder), expressionBuilder)
internal DelegateAssertionBuilder(Action action, string? expressionBuilder) : base(LazyAssertionData.Create(action, expressionBuilder), expressionBuilder)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class InvokableAssertionBuilder<TActual> :
{
protected readonly ISource Source;

internal InvokableAssertionBuilder(ISource source) : base(source.AssertionDataTask, source.ActualExpression!,
internal InvokableAssertionBuilder(ISource source) : base(source.LazyAssertionData, source.ActualExpression!,
source.ExpressionBuilder, source.Assertions)
{
Source = source;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace TUnit.Assertions.AssertionBuilders;

public class InvokableValueDelegateAssertionBuilder<TActual> : InvokableAssertionBuilder<TActual>
{
internal InvokableValueDelegateAssertionBuilder(ValueTask<AssertionData> assertionDataDelegate, AssertionBuilder assertionBuilder) : base(assertionBuilder)
internal InvokableValueDelegateAssertionBuilder(LazyAssertionData assertionDataDelegate, AssertionBuilder assertionBuilder) : base(assertionBuilder)
{
}

Expand Down
2 changes: 1 addition & 1 deletion TUnit.Assertions/AssertionBuilders/OrAssertionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertionBuilders;

public class OrAssertionBuilder : AssertionBuilder, IOrAssertionBuilder
{
internal OrAssertionBuilder(AssertionBuilder assertionBuilder) : base(((ISource) assertionBuilder).AssertionDataTask, (
internal OrAssertionBuilder(AssertionBuilder assertionBuilder) : base(((ISource) assertionBuilder).LazyAssertionData, (
(ISource) assertionBuilder).ActualExpression!, (
(ISource) assertionBuilder).ExpressionBuilder, ((ISource) assertionBuilder).Assertions)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertionBuilders;

public class ValueAssertionBuilder<TActual> : AssertionBuilder, IValueSource<TActual>
{
internal ValueAssertionBuilder(TActual value, string? expressionBuilder) : base(value.AsAssertionData(expressionBuilder), expressionBuilder)
internal ValueAssertionBuilder(TActual value, string? expressionBuilder) : base(LazyAssertionData.Create(value, expressionBuilder), expressionBuilder)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertionBuilders;
public class ValueDelegateAssertionBuilder<TActual>
: AssertionBuilder, IValueDelegateSource<TActual>
{
internal ValueDelegateAssertionBuilder(Func<TActual> function, string? expressionBuilder) : base(function.AsAssertionData(expressionBuilder), expressionBuilder)
internal ValueDelegateAssertionBuilder(Func<TActual> function, string? expressionBuilder) : base(LazyAssertionData.Create(function, expressionBuilder), expressionBuilder)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ protected override async ValueTask<AssertionResult> GetResult(
AssertionMetadata assertionMetadata
)
{
return await assertCondition.GetAssertionResult(await source.AssertionDataTask);
return await assertCondition.GetAssertionResult(await source.LazyAssertionData.GetResultAsync());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ protected override async ValueTask<AssertionResult> GetResult(
AssertionMetadata assertionMetadata
)
{
return await convertToAssertCondition.GetAssertionResult(await source.AssertionDataTask);
return await convertToAssertCondition.GetAssertionResult(await source.LazyAssertionData.GetResultAsync());
}
}
Loading
Loading