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
2 changes: 1 addition & 1 deletion Pipeline/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ partial class Build : NukeBuild
/// <para />
/// Afterward, you can update the package reference in `Directory.Packages.props` and reset this flag.
/// </summary>
readonly BuildScope BuildScope = BuildScope.Default;
readonly BuildScope BuildScope = BuildScope.CoreOnly;

[Parameter("Github Token")] readonly string GithubToken;

Expand Down
10 changes: 8 additions & 2 deletions Source/aweXpect.Core/Delegates/ThatDelegate.Throws.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public ThatDelegateThrows<TException> Throws<TException>()
{
ThrowsOption throwOptions = new();
return new ThatDelegateThrows<TException>(ExpectationBuilder
.AddConstraint((it, grammars) => new DelegateIsNotNullConstraint(it, grammars))
.AddConstraint((it, grammars) => new DelegateIsNotNullWithinTimeoutConstraint(it, grammars, throwOptions))
.ForWhich<DelegateValue, Exception?>(d => d.Exception)
.AddConstraint((it, grammars) => new ThrowsConstraint(it, grammars, typeof(TException), throwOptions))
.And(" "),
Expand All @@ -32,7 +32,7 @@ public ThatDelegateThrows<Exception> Throws(Type exceptionType)
{
ThrowsOption throwOptions = new();
return new ThatDelegateThrows<Exception>(ExpectationBuilder
.AddConstraint((it, grammars) => new DelegateIsNotNullConstraint(it, grammars))
.AddConstraint((it, grammars) => new DelegateIsNotNullWithinTimeoutConstraint(it, grammars, throwOptions))
.ForWhich<DelegateValue, Exception?>(d => d.Exception)
.AddConstraint((it, grammars) => new ThrowsConstraint(it, grammars, exceptionType, throwOptions))
.And(" "),
Expand Down Expand Up @@ -89,6 +89,12 @@ public override void AppendExpectation(StringBuilder stringBuilder, string? inde
{
stringBuilder.Append("throws ").Append(Formatter.Format(exceptionType).PrependAOrAn());
}

if (throwOptions.ExecutionTimeOptions is not null)
{
stringBuilder.Append(' ');
throwOptions.ExecutionTimeOptions.AppendTo(stringBuilder, "in ");
}
}

public override void AppendResult(StringBuilder stringBuilder, string? indentation = null)
Expand Down
10 changes: 8 additions & 2 deletions Source/aweXpect.Core/Delegates/ThatDelegate.ThrowsExactly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public ThatDelegateThrows<TException> ThrowsExactly<TException>()
{
ThrowsOption throwOptions = new();
return new ThatDelegateThrows<TException>(ExpectationBuilder
.AddConstraint((it, grammars) => new DelegateIsNotNullConstraint(it, grammars))
.AddConstraint((it, grammars) => new DelegateIsNotNullWithinTimeoutConstraint(it, grammars, throwOptions))
.ForWhich<DelegateValue, Exception?>(d => d.Exception)
.AddConstraint((it, grammars)
=> new ThrowsExactlyConstraint(it, grammars, typeof(TException), throwOptions))
Expand All @@ -33,7 +33,7 @@ public ThatDelegateThrows<Exception> ThrowsExactly(Type exceptionType)
{
ThrowsOption throwOptions = new();
return new ThatDelegateThrows<Exception>(ExpectationBuilder
.AddConstraint((it, grammars) => new DelegateIsNotNullConstraint(it, grammars))
.AddConstraint((it, grammars) => new DelegateIsNotNullWithinTimeoutConstraint(it, grammars, throwOptions))
.ForWhich<DelegateValue, Exception?>(d => d.Exception)
.AddConstraint((it, grammars) => new ThrowsExactlyConstraint(it, grammars, exceptionType, throwOptions))
.And(" "),
Expand Down Expand Up @@ -86,6 +86,12 @@ public override void AppendExpectation(StringBuilder stringBuilder, string? inde
{
stringBuilder.Append("throws exactly ").Append(Formatter.Format(exceptionType).PrependAOrAn());
}

if (throwOptions.ExecutionTimeOptions is not null)
{
stringBuilder.Append(' ');
throwOptions.ExecutionTimeOptions.AppendTo(stringBuilder, "in ");
}
}

public override void AppendResult(StringBuilder stringBuilder, string? indentation = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public ThatDelegateThrows<Exception> ThrowsException()
{
ThrowsOption throwOptions = new();
return new ThatDelegateThrows<Exception>(ExpectationBuilder
.AddConstraint((it, grammars) => new DelegateIsNotNullConstraint(it, grammars))
.AddConstraint((it, grammars) => new DelegateIsNotNullWithinTimeoutConstraint(it, grammars, throwOptions))
.ForWhich<DelegateValue, Exception?>(d => d.Exception)
.AddConstraint((it, grammars) => new ThrowsConstraint(it, grammars, typeof(Exception), throwOptions))
.And(" "),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ public ConstraintResult IsMetBy(DelegateValue<T> value)
}

public override void AppendExpectation(StringBuilder stringBuilder, string? indentation = null)
=> stringBuilder.Append("executes in ").Append(options);
{
stringBuilder.Append("executes ");
options.AppendTo(stringBuilder, "in ");
}

public override void AppendResult(StringBuilder stringBuilder, string? indentation = null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ public ConstraintResult IsMetBy(DelegateValue value)
}

public override void AppendExpectation(StringBuilder stringBuilder, string? indentation = null)
=> stringBuilder.Append("executes in ").Append(options);
{
stringBuilder.Append("executes ");
options.AppendTo(stringBuilder, "in ");
}

public override void AppendResult(StringBuilder stringBuilder, string? indentation = null)
{
Expand Down
34 changes: 31 additions & 3 deletions Source/aweXpect.Core/Delegates/ThatDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using aweXpect.Core.Constraints;
using aweXpect.Core.Helpers;
using aweXpect.Core.Sources;
using aweXpect.Options;

namespace aweXpect.Delegates;

Expand Down Expand Up @@ -34,13 +35,28 @@ internal static string FormatForMessage(Exception? exception)
return message;
}

private sealed class DelegateIsNotNullConstraint(string it, ExpectationGrammars grammars)
private sealed class DelegateIsNotNullWithinTimeoutConstraint(string it, ExpectationGrammars grammars, ThrowsOption options)
: ConstraintResult(grammars),
IValueConstraint<DelegateValue>
{
private DelegateValue? _actual;
public ConstraintResult IsMetBy(DelegateValue value)
{
Outcome = value.IsNull ? Outcome.Failure : Outcome.Success;
_actual = value;
if (value.IsNull)
{
Outcome = Outcome.Failure;
return this;
}

if (options.ExecutionTimeOptions is not null &&
!options.ExecutionTimeOptions.IsWithinLimit(value.Duration))
{
Outcome = Outcome.Failure;
return this;
}

Outcome = Outcome.Success;
return this;
}

Expand All @@ -50,7 +66,17 @@ public override void AppendExpectation(StringBuilder stringBuilder, string? inde
}

public override void AppendResult(StringBuilder stringBuilder, string? indentation = null)
=> stringBuilder.ItWasNull(it);
{
if (_actual?.IsNull != false)
{
stringBuilder.ItWasNull(it);
}
else if (options.ExecutionTimeOptions is not null)
{
stringBuilder.Append(it).Append(" took ");
options.ExecutionTimeOptions.AppendFailureResult(stringBuilder, _actual.Duration);
}
}

public override bool TryGetValue<TValue>([NotNullWhen(true)] out TValue? value) where TValue : default
{
Expand All @@ -65,6 +91,8 @@ public override ConstraintResult Negate()
internal class ThrowsOption
{
public bool DoCheckThrow { get; private set; } = true;

public TimeSpanEqualityOptions? ExecutionTimeOptions { get; set; }

public void CheckThrow(bool doCheckThrow) => DoCheckThrow = doCheckThrow;
}
Expand Down
8 changes: 1 addition & 7 deletions Source/aweXpect.Core/Delegates/ThatDelegateThrows.Which.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
using System;
using System.Linq.Expressions;
using aweXpect.Core;
using aweXpect.Core.Sources;
using aweXpect.Results;
using aweXpect.Core;

namespace aweXpect.Delegates;

public partial class ThatDelegateThrows<TException>
{

/// <summary>
/// Further expectations on the <typeparamref name="TException" />
/// </summary>
public IThat<TException> Which
=> new ThatSubject<TException>(ExpectationBuilder.And(" which "));

}
6 changes: 4 additions & 2 deletions Source/aweXpect.Core/Delegates/ThatDelegateThrows.Whose.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ public partial class ThatDelegateThrows<TException>
public AndOrResult<TException, ThatDelegateThrows<TException>> Whose<TMember>(
Func<TException, TMember?> memberSelector,
Action<IThat<TMember?>> expectations,
[CallerArgumentExpression("memberSelector")] string doNotPopulateThisValue = "")
[CallerArgumentExpression("memberSelector")]
string doNotPopulateThisValue = "")
=> new(ExpectationBuilder.ForMember(
MemberAccessor<TException, TMember?>.FromFuncAsMemberAccessor(memberSelector, doNotPopulateThisValue),
MemberAccessor<TException, TMember?>.FromFuncAsMemberAccessor(memberSelector,
doNotPopulateThisValue),
(member, expectation) => expectation.Append("whose ").Append(member))
.AddExpectations(e => expectations(new ThatSubject<TMember?>(e))),
this);
Expand Down
18 changes: 18 additions & 0 deletions Source/aweXpect.Core/Delegates/ThatDelegateThrows.Within.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using aweXpect.Options;

namespace aweXpect.Delegates;

public partial class ThatDelegateThrows<TException>
{
/// <summary>
/// Verifies that the delegate throws within the given <paramref name="duration" />.
/// </summary>
public ThatDelegateThrows<TException> Within(TimeSpan duration)
{
TimeSpanEqualityOptions options = new();
options.Within(duration);
_throwOptions.ExecutionTimeOptions = options;
return this;
}
}
58 changes: 50 additions & 8 deletions Source/aweXpect.Core/Options/TimeSpanEqualityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,17 @@ public bool IsWithinLimit(TimeSpan? actual)
public void AppendFailureResult(StringBuilder stringBuilder, TimeSpan actual)
=> _limit?.AppendFailureResult(stringBuilder, actual);

/// <inheritdoc />
public override string ToString() => _limit?.ToString() ?? "<no limit specified>";
/// <summary>
/// Appends the <paramref name="prefix" /> and the option description to the <paramref name="stringBuilder" />.
/// </summary>
public void AppendTo(StringBuilder stringBuilder, string prefix)
=> _limit?.AppendTo(stringBuilder, prefix);

/// <summary>
/// Verifies that the value is within the given <paramref name="duration" />.
/// </summary>
public void Within(TimeSpan duration)
=> _limit = new MaximumLimit(duration, true);

/// <summary>
/// Verifies that the value is at most <paramref name="maximum" />.
Expand Down Expand Up @@ -74,15 +83,23 @@ private abstract record Limit

public virtual void AppendFailureResult(StringBuilder stringBuilder, TimeSpan actual)
=> Formatter.Format(stringBuilder, actual);

public abstract void AppendTo(StringBuilder stringBuilder, string prefix);
}

private sealed record ApproximatelyLimit(TimeSpan Expected, TimeSpan Tolerance) : Limit
{
public override bool IsWithinLimit(TimeSpan actual)
=> actual >= Expected - Tolerance && actual <= Expected + Tolerance;

public override string ToString()
=> $"approximately {Formatter.Format(Expected)} ± {Formatter.Format(Tolerance)}";
public override void AppendTo(StringBuilder stringBuilder, string prefix)
{
stringBuilder.Append(prefix);
stringBuilder.Append("approximately ");
Formatter.Format(stringBuilder, Expected);
stringBuilder.Append(" ± ");
Formatter.Format(stringBuilder, Tolerance);
}

public override void AppendFailureResult(StringBuilder stringBuilder, TimeSpan actual)
{
Expand All @@ -100,7 +117,14 @@ private sealed record BetweenLimit(TimeSpan Minimum, TimeSpan Maximum) : Limit
public override bool IsWithinLimit(TimeSpan actual)
=> actual >= Minimum && actual <= Maximum;

public override string ToString() => $"between {Formatter.Format(Minimum)} and {Formatter.Format(Maximum)}";
public override void AppendTo(StringBuilder stringBuilder, string prefix)
{
stringBuilder.Append(prefix);
stringBuilder.Append("between ");
Formatter.Format(stringBuilder, Minimum);
stringBuilder.Append(" and ");
Formatter.Format(stringBuilder, Maximum);
}

public override void AppendFailureResult(StringBuilder stringBuilder, TimeSpan actual)
{
Expand All @@ -118,7 +142,12 @@ private sealed record MinimumLimit(TimeSpan Minimum) : Limit
public override bool IsWithinLimit(TimeSpan actual)
=> actual >= Minimum;

public override string ToString() => $"at least {Formatter.Format(Minimum)}";
public override void AppendTo(StringBuilder stringBuilder, string prefix)
{
stringBuilder.Append(prefix);
stringBuilder.Append("at least ");
Formatter.Format(stringBuilder, Minimum);
}

public override void AppendFailureResult(StringBuilder stringBuilder, TimeSpan actual)
{
Expand All @@ -127,11 +156,24 @@ public override void AppendFailureResult(StringBuilder stringBuilder, TimeSpan a
}
}

private sealed record MaximumLimit(TimeSpan Maximum) : Limit
private sealed record MaximumLimit(TimeSpan Maximum, bool IsWithin = false) : Limit
{
public override bool IsWithinLimit(TimeSpan actual)
=> actual <= Maximum;

public override string ToString() => $"at most {Formatter.Format(Maximum)}";
public override void AppendTo(StringBuilder stringBuilder, string prefix)
{
if (IsWithin)
{
stringBuilder.Append("within ");
Formatter.Format(stringBuilder, Maximum);
}
else
{
stringBuilder.Append(prefix);
stringBuilder.Append("at most ");
Formatter.Format(stringBuilder, Maximum);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ namespace aweXpect.Delegates
where TInnerException : System.Exception { }
public aweXpect.Results.AndOrResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithInnerException() { }
public aweXpect.Results.AndOrResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithInnerException(System.Action<aweXpect.Core.IThat<System.Exception?>> expectations) { }
public aweXpect.Delegates.ThatDelegateThrows<TException> Within(System.TimeSpan duration) { }
}
}
namespace aweXpect.Equivalency
Expand Down Expand Up @@ -846,12 +847,13 @@ namespace aweXpect.Options
{
public TimeSpanEqualityOptions() { }
public void AppendFailureResult(System.Text.StringBuilder stringBuilder, System.TimeSpan actual) { }
public void AppendTo(System.Text.StringBuilder stringBuilder, string prefix) { }
public void Approximately(System.TimeSpan expected, System.TimeSpan tolerance) { }
public void AtLeast(System.TimeSpan minimum) { }
public void AtMost(System.TimeSpan maximum) { }
public void Between(System.TimeSpan minimum, System.TimeSpan maximum) { }
public bool IsWithinLimit(System.TimeSpan? actual) { }
public override string ToString() { }
public void Within(System.TimeSpan duration) { }
}
public class TimeTolerance
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ namespace aweXpect.Delegates
where TInnerException : System.Exception { }
public aweXpect.Results.AndOrResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithInnerException() { }
public aweXpect.Results.AndOrResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithInnerException(System.Action<aweXpect.Core.IThat<System.Exception?>> expectations) { }
public aweXpect.Delegates.ThatDelegateThrows<TException> Within(System.TimeSpan duration) { }
}
}
namespace aweXpect.Equivalency
Expand Down Expand Up @@ -829,12 +830,13 @@ namespace aweXpect.Options
{
public TimeSpanEqualityOptions() { }
public void AppendFailureResult(System.Text.StringBuilder stringBuilder, System.TimeSpan actual) { }
public void AppendTo(System.Text.StringBuilder stringBuilder, string prefix) { }
public void Approximately(System.TimeSpan expected, System.TimeSpan tolerance) { }
public void AtLeast(System.TimeSpan minimum) { }
public void AtMost(System.TimeSpan maximum) { }
public void Between(System.TimeSpan minimum, System.TimeSpan maximum) { }
public bool IsWithinLimit(System.TimeSpan? actual) { }
public override string ToString() { }
public void Within(System.TimeSpan duration) { }
}
public class TimeTolerance
{
Expand Down
Loading