Skip to content

Commit

Permalink
SAVEPOINT
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisdoomen authored and Dennis Doomen committed Apr 18, 2024
1 parent 549f752 commit adaec55
Show file tree
Hide file tree
Showing 156 changed files with 1,785 additions and 2,650 deletions.
10 changes: 5 additions & 5 deletions Src/FluentAssertions/AndWhich.cs
Expand Up @@ -9,16 +9,16 @@ namespace FluentAssertions;

public class AndWhich<TParent, TSubject> : AndConstraint<TParent>
{
private readonly Assertion assertion;
private readonly AssertionChain assertionChain;
private readonly string pathPostfix;
private readonly Lazy<TSubject> getSubject;

public AndWhich(TParent parent, TSubject subject, Assertion assertion, string pathPostfix)
public AndWhich(TParent parent, TSubject subject, AssertionChain assertionChain, string pathPostfix)
: base(parent)
{
getSubject = new Lazy<TSubject>(() => subject);

this.assertion = assertion;
this.assertionChain = assertionChain;
this.pathPostfix = pathPostfix;
}

Expand All @@ -43,9 +43,9 @@ public TSubject Which
{
get
{
assertion.AddCallerPostfix(pathPostfix);
assertionChain.AddCallerPostfix(pathPostfix);

Assertion.ReuseOnce(assertion);
AssertionChain.ReuseOnce(assertionChain);

return getSubject.Value;
}
Expand Down
171 changes: 68 additions & 103 deletions Src/FluentAssertions/AssertionExtensions.cs

Large diffs are not rendered by default.

288 changes: 144 additions & 144 deletions Src/FluentAssertions/Collections/GenericCollectionAssertions.cs

Large diffs are not rendered by default.

108 changes: 54 additions & 54 deletions Src/FluentAssertions/Collections/GenericDictionaryAssertions.cs

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions Src/FluentAssertions/Collections/StringCollectionAssertions.cs
Expand Up @@ -12,8 +12,8 @@ public class StringCollectionAssertions : StringCollectionAssertions<IEnumerable
/// <summary>
/// Initializes a new instance of the <see cref="StringCollectionAssertions"/> class.
/// </summary>
public StringCollectionAssertions(IEnumerable<string> actualValue, Assertion assertion)
: base(actualValue, assertion)
public StringCollectionAssertions(IEnumerable<string> actualValue, AssertionChain assertionChain)
: base(actualValue, assertionChain)
{
}
}
Expand All @@ -25,8 +25,8 @@ public class StringCollectionAssertions<TCollection>
/// <summary>
/// Initializes a new instance of the <see cref="StringCollectionAssertions{TCollection}"/> class.
/// </summary>
public StringCollectionAssertions(TCollection actualValue, Assertion assertion)
: base(actualValue, assertion)
public StringCollectionAssertions(TCollection actualValue, AssertionChain assertionChain)
: base(actualValue, assertionChain)
{
}
}
Expand All @@ -35,15 +35,15 @@ public class StringCollectionAssertions<TCollection, TAssertions> : GenericColle
where TCollection : IEnumerable<string>
where TAssertions : StringCollectionAssertions<TCollection, TAssertions>
{
private readonly Assertion assertion;
private readonly AssertionChain assertionChain;

/// <summary>
/// Initializes a new instance of the <see cref="StringCollectionAssertions{TCollection, TAssertions}"/> class.
/// </summary>
public StringCollectionAssertions(TCollection actualValue, Assertion assertion)
: base(actualValue, assertion)
public StringCollectionAssertions(TCollection actualValue, AssertionChain assertionChain)
: base(actualValue, assertionChain)
{
this.assertion = assertion;
this.assertionChain = assertionChain;
}

/// <summary>
Expand Down Expand Up @@ -251,16 +251,16 @@ public AndConstraint<TAssertions> BeEquivalentTo(params string[] expectation)
Guard.ThrowIfArgumentIsEmpty(wildcardPattern, nameof(wildcardPattern),
"Cannot match strings in collection against an empty string. Provide a wildcard pattern or use the Contain method.");

assertion
assertionChain
.BecauseOf(because, becauseArgs)
.ForCondition(Subject is not null)
.FailWith("Expected {context:collection} to contain a match of {0}{reason}, but found <null>.", wildcardPattern);

IEnumerable<string> matched = [];

if (assertion.Succeeded)
if (assertionChain.Succeeded)
{
assertion
assertionChain
.BecauseOf(because, becauseArgs)
.ForCondition(ContainsMatch(wildcardPattern))
.FailWith("Expected {context:collection} {0} to contain a match of {1}{reason}.", Subject, wildcardPattern);
Expand Down Expand Up @@ -336,15 +336,15 @@ private IEnumerable<string> AllThatMatch(string wildcardPattern)
Guard.ThrowIfArgumentIsEmpty(wildcardPattern, nameof(wildcardPattern),
"Cannot match strings in collection against an empty string. Provide a wildcard pattern or use the NotContain method.");

assertion
assertionChain
.BecauseOf(because, becauseArgs)
.ForCondition(Subject is not null)
.FailWith("Did not expect {context:collection} to contain a match of {0}{reason}, but found <null>.",
wildcardPattern);

if (assertion.Succeeded)
if (assertionChain.Succeeded)
{
assertion
assertionChain
.BecauseOf(because, becauseArgs)
.ForCondition(NotContainsMatch(wildcardPattern))
.FailWith("Did not expect {context:collection} {0} to contain a match of {1}{reason}.", Subject, wildcardPattern);
Expand Down
Expand Up @@ -9,8 +9,8 @@ namespace FluentAssertions.Collections;
public class SubsequentOrderingAssertions<T>
: SubsequentOrderingGenericCollectionAssertions<IEnumerable<T>, T, SubsequentOrderingAssertions<T>>
{
public SubsequentOrderingAssertions(IEnumerable<T> actualValue, IOrderedEnumerable<T> previousOrderedEnumerable, Assertion assertion)
: base(actualValue, previousOrderedEnumerable, assertion)
public SubsequentOrderingAssertions(IEnumerable<T> actualValue, IOrderedEnumerable<T> previousOrderedEnumerable, AssertionChain assertionChain)
: base(actualValue, previousOrderedEnumerable, assertionChain)
{
}
}
Expand Up @@ -17,8 +17,8 @@ public class SubsequentOrderingGenericCollectionAssertions<TCollection, T, TAsse
private readonly IOrderedEnumerable<T> previousOrderedEnumerable;
private bool subsequentOrdering;

public SubsequentOrderingGenericCollectionAssertions(TCollection actualValue, IOrderedEnumerable<T> previousOrderedEnumerable, Assertion assertion)
: base(actualValue, assertion)
public SubsequentOrderingGenericCollectionAssertions(TCollection actualValue, IOrderedEnumerable<T> previousOrderedEnumerable, AssertionChain assertionChain)
: base(actualValue, assertionChain)
{
this.previousOrderedEnumerable = previousOrderedEnumerable;
}
Expand Down Expand Up @@ -168,8 +168,8 @@ public class SubsequentOrderingGenericCollectionAssertions<TCollection, T>
: SubsequentOrderingGenericCollectionAssertions<TCollection, T, SubsequentOrderingGenericCollectionAssertions<TCollection, T>>
where TCollection : IEnumerable<T>
{
public SubsequentOrderingGenericCollectionAssertions(TCollection actualValue, IOrderedEnumerable<T> previousOrderedEnumerable, Assertion assertion)
: base(actualValue, previousOrderedEnumerable, assertion)
public SubsequentOrderingGenericCollectionAssertions(TCollection actualValue, IOrderedEnumerable<T> previousOrderedEnumerable, AssertionChain assertionChain)
: base(actualValue, previousOrderedEnumerable, assertionChain)
{
}
}
4 changes: 2 additions & 2 deletions Src/FluentAssertions/EnumAssertionsExtensions.cs
Expand Up @@ -20,7 +20,7 @@ public static class EnumAssertionsExtensions
public static EnumAssertions<TEnum> Should<TEnum>(this TEnum @enum)
where TEnum : struct, Enum
{
return new EnumAssertions<TEnum>(@enum, Assertion.GetOrCreate());
return new EnumAssertions<TEnum>(@enum, AssertionChain.GetOrCreate());
}

/// <summary>
Expand All @@ -31,6 +31,6 @@ public static EnumAssertions<TEnum> Should<TEnum>(this TEnum @enum)
public static NullableEnumAssertions<TEnum> Should<TEnum>(this TEnum? @enum)
where TEnum : struct, Enum
{
return new NullableEnumAssertions<TEnum>(@enum, Assertion.GetOrCreate());
return new NullableEnumAssertions<TEnum>(@enum, AssertionChain.GetOrCreate());
}
}
6 changes: 3 additions & 3 deletions Src/FluentAssertions/Equivalency/EquivalencyStep.cs
Expand Up @@ -7,21 +7,21 @@ namespace FluentAssertions.Equivalency;
/// </summary>
public abstract class EquivalencyStep<T> : IEquivalencyStep
{
public EquivalencyResult Handle(Comparands comparands, Assertion assertion, IEquivalencyValidationContext context,
public EquivalencyResult Handle(Comparands comparands, AssertionChain assertionChain, IEquivalencyValidationContext context,
IValidateChildNodeEquivalency nestedValidator)
{
if (!typeof(T).IsAssignableFrom(comparands.GetExpectedType(context.Options)))
{
return EquivalencyResult.ContinueWithNext;
}

return OnHandle(comparands, assertion, context, nestedValidator);
return OnHandle(comparands, assertionChain, context, nestedValidator);
}

/// <summary>
/// Implements <see cref="IEquivalencyStep.Handle"/>, but only gets called when the expected type matches <typeparamref name="T"/>.
/// </summary>
protected abstract EquivalencyResult OnHandle(Comparands comparands, Assertion assertion,
protected abstract EquivalencyResult OnHandle(Comparands comparands, AssertionChain assertionChain,
IEquivalencyValidationContext context,
IValidateChildNodeEquivalency nestedValidator);
}
28 changes: 14 additions & 14 deletions Src/FluentAssertions/Equivalency/EquivalencyValidator.cs
Expand Up @@ -17,7 +17,7 @@ public void AssertEquality(Comparands comparands, EquivalencyValidationContext c

var getIdentifierOnce = new Lazy<string>(() => scope.GetIdentifier());

var assertion = Assertion.GetOrCreate(() => scope, () => getIdentifierOnce.Value);
var assertion = AssertionChain.GetOrCreate(() => scope, () => getIdentifierOnce.Value);

assertion.WithReportable("configuration", () => context.Options.ToString());
assertion.BecauseOf(context.Reason);
Expand All @@ -30,52 +30,52 @@ public void AssertEquality(Comparands comparands, EquivalencyValidationContext c
}
}

private void RecursivelyAssertEquivalencyOf(Comparands comparands, Assertion assertion, IEquivalencyValidationContext context)
private void RecursivelyAssertEquivalencyOf(Comparands comparands, AssertionChain assertionChain, IEquivalencyValidationContext context)
{
AssertEquivalencyOf(comparands, assertion, context);
AssertEquivalencyOf(comparands, assertionChain, context);
}

public void AssertEquivalencyOf(Comparands comparands, Assertion assertion, IEquivalencyValidationContext context)
public void AssertEquivalencyOf(Comparands comparands, AssertionChain assertionChain, IEquivalencyValidationContext context)
{
if (ShouldContinueThisDeep(context.CurrentNode, context.Options, assertion))
if (ShouldContinueThisDeep(context.CurrentNode, context.Options, assertionChain))
{
TrackWhatIsNeededToProvideContextToFailures(assertion, comparands, context.CurrentNode);
TrackWhatIsNeededToProvideContextToFailures(assertionChain, comparands, context.CurrentNode);

if (!context.IsCyclicReference(comparands.Expectation))
{
TryToProveNodesAreEquivalent(assertion, comparands, context);
TryToProveNodesAreEquivalent(assertionChain, comparands, context);
}
}
}

private static bool ShouldContinueThisDeep(INode currentNode, IEquivalencyOptions options,
Assertion assertion)
AssertionChain assertionChain)
{
bool shouldRecurse = options.AllowInfiniteRecursion || currentNode.Depth <= MaxDepth;
if (!shouldRecurse)
{
// This will throw, unless we're inside an AssertionScope
assertion.FailWith($"The maximum recursion depth of {MaxDepth} was reached. ");
assertionChain.FailWith($"The maximum recursion depth of {MaxDepth} was reached. ");
}

return shouldRecurse;
}

private static void TrackWhatIsNeededToProvideContextToFailures(Assertion assertion, Comparands comparands, INode currentNode)
private static void TrackWhatIsNeededToProvideContextToFailures(AssertionChain assertionChain, Comparands comparands, INode currentNode)
{
assertion.Context = new Lazy<string>(() => currentNode.Description);
assertion.TrackComparands(comparands.Subject, comparands.Expectation);
assertionChain.Context = new Lazy<string>(() => currentNode.Description);
assertionChain.TrackComparands(comparands.Subject, comparands.Expectation);
}

private void TryToProveNodesAreEquivalent(Assertion assertion, Comparands comparands, IEquivalencyValidationContext context)
private void TryToProveNodesAreEquivalent(AssertionChain assertionChain, Comparands comparands, IEquivalencyValidationContext context)
{
using var _ = context.Tracer.WriteBlock(node => node.Description);

Func<IEquivalencyStep, GetTraceMessage> getMessage = step => _ => $"Equivalency was proven by {step.GetType().Name}";

foreach (IEquivalencyStep step in AssertionOptions.EquivalencyPlan)
{
var result = step.Handle(comparands, assertion, context, this);
var result = step.Handle(comparands, assertionChain, context, this);
if (result == EquivalencyResult.EquivalencyProven)
{
context.Tracer.WriteLine(getMessage(step));
Expand Down
2 changes: 1 addition & 1 deletion Src/FluentAssertions/Equivalency/IEquivalencyStep.cs
Expand Up @@ -17,6 +17,6 @@ public interface IEquivalencyStep
/// <remarks>
/// May throw when preconditions are not met or if it detects mismatching data.
/// </remarks>
EquivalencyResult Handle(Comparands comparands, Assertion assertion, IEquivalencyValidationContext context,
EquivalencyResult Handle(Comparands comparands, AssertionChain assertionChain, IEquivalencyValidationContext context,
IValidateChildNodeEquivalency nestedValidator);
}
4 changes: 2 additions & 2 deletions Src/FluentAssertions/Equivalency/IMemberMatchingRule.cs
Expand Up @@ -25,10 +25,10 @@ public interface IMemberMatchingRule
/// </param>
/// <param name="parent"></param>
/// <param name="options"></param>
/// <param name="assertion"></param>
/// <param name="assertionChain"></param>
/// <returns>
/// Returns the <see cref="IMember"/> of the property with which to compare the subject with, or <see langword="null"/>
/// if no match was found.
/// </returns>
IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, Assertion assertion);
IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, AssertionChain assertionChain);
}
Expand Up @@ -7,5 +7,5 @@ public interface IValidateChildNodeEquivalency
/// <summary>
/// Runs a deep recursive equivalency assertion on the provided <paramref name="comparands"/>.
/// </summary>
void AssertEquivalencyOf(Comparands comparands, Assertion assertion, IEquivalencyValidationContext context);
void AssertEquivalencyOf(Comparands comparands, AssertionChain assertionChain, IEquivalencyValidationContext context);
}
Expand Up @@ -30,7 +30,7 @@ public MappedMemberMatchingRule(string expectationMemberName, string subjectMemb
this.subjectMemberName = subjectMemberName;
}

public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, Assertion assertion)
public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, AssertionChain assertionChain)
{
if (parent.Type.IsSameOrInherits(typeof(TExpectation)) && subject is TSubject &&
expectedMember.Name == expectationMemberName)
Expand Down
Expand Up @@ -43,7 +43,7 @@ public MappedPathMatchingRule(string expectationMemberPath, string subjectMember
}
}

public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, Assertion assertion)
public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, AssertionChain assertionChain)
{
MemberPath path = expectationPath;

Expand Down
Expand Up @@ -9,7 +9,7 @@ namespace FluentAssertions.Equivalency.Matching;
/// </summary>
internal class MustMatchByNameRule : IMemberMatchingRule
{
public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, Assertion assertion)
public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, AssertionChain assertionChain)
{
IMember subjectMember = null;

Expand All @@ -33,12 +33,12 @@ public IMember Match(IMember expectedMember, object subject, INode parent, IEqui

if (subjectMember is null)
{
assertion.FailWith(
assertionChain.FailWith(
$"Expectation has {expectedMember.Description} that the other object does not have.");
}
else if (options.IgnoreNonBrowsableOnSubject && !subjectMember.IsBrowsable)
{
assertion.FailWith(
assertionChain.FailWith(
$"Expectation has {expectedMember.Description} that is non-browsable in the other object, and non-browsable " +
"members on the subject are ignored with the current configuration");
}
Expand Down
Expand Up @@ -9,7 +9,7 @@ namespace FluentAssertions.Equivalency.Matching;
/// </summary>
internal class TryMatchByNameRule : IMemberMatchingRule
{
public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, Assertion assertion)
public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyOptions options, AssertionChain assertionChain)
{
if (options.IncludedProperties != MemberVisibility.None)
{
Expand Down
Expand Up @@ -10,7 +10,7 @@ namespace FluentAssertions.Equivalency;
/// </summary>
internal class MultiDimensionalArrayEquivalencyStep : IEquivalencyStep
{
public EquivalencyResult Handle(Comparands comparands, Assertion assertion, IEquivalencyValidationContext context,
public EquivalencyResult Handle(Comparands comparands, AssertionChain assertionChain, IEquivalencyValidationContext context,
IValidateChildNodeEquivalency nestedValidator)
{
if (comparands.Expectation is not Array expectationAsArray || expectationAsArray.Rank == 1)
Expand All @@ -36,7 +36,7 @@ internal class MultiDimensionalArrayEquivalencyStep : IEquivalencyStep

IEquivalencyValidationContext itemContext = context.AsCollectionItem<object>(listOfIndices);

nestedValidator.AssertEquivalencyOf(new Comparands(subject, expectation, typeof(object)), assertion, itemContext);
nestedValidator.AssertEquivalencyOf(new Comparands(subject, expectation, typeof(object)), assertionChain, itemContext);
}
while (digit.Increment());
}
Expand Down
Expand Up @@ -22,7 +22,7 @@ public class AssertionRuleEquivalencyStep<TSubject> : IEquivalencyStep
description = predicate.ToString();
}

public EquivalencyResult Handle(Comparands comparands, Assertion assertion, IEquivalencyValidationContext context,
public EquivalencyResult Handle(Comparands comparands, AssertionChain assertionChain, IEquivalencyValidationContext context,
IValidateChildNodeEquivalency nestedValidator)
{
bool success = false;
Expand All @@ -41,7 +41,7 @@ public class AssertionRuleEquivalencyStep<TSubject> : IEquivalencyStep
{
// Convert into a child context
context = context.Clone();
converter.Handle(comparands, assertion, context, nestedValidator);
converter.Handle(comparands, assertionChain, context, nestedValidator);
converted = true;
}

Expand All @@ -50,7 +50,7 @@ public class AssertionRuleEquivalencyStep<TSubject> : IEquivalencyStep
// Try again after conversion
success = ExecuteAssertion(comparands, context);

if (assertion.Succeeded)
if (assertionChain.Succeeded)
{
// If the assertion succeeded after conversion, discard the failures from
// the previous attempt. If it didn't, let the scope throw with those failures.
Expand Down

0 comments on commit adaec55

Please sign in to comment.