NUnitEqualityComparer
NUnitEqualityComparer encapsulates NUnit's handling of
equality tests between objects.
using NUnit.Framework.Constraints.Comparers;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace NUnit.Framework.Constraints
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public sealed class NUnitEqualityComparer
{
[System.Runtime.CompilerServices.NullableContext(0)]
private delegate EqualMethodResult EqualMethod (object x, object y, ref Tolerance tolerance, ComparisonState state, NUnitEqualityComparer equalityComparer);
[System.Runtime.CompilerServices.NullableContext(2)]
[System.Runtime.CompilerServices.Nullable(0)]
public sealed class FailurePoint
{
public long Position;
public object ExpectedValue;
public object ActualValue;
public bool ExpectedHasData;
public bool ActualHasData;
}
private static readonly EqualMethod[] Comparers = new EqualMethod[18] {
ArraysComparer.Equal,
DictionariesComparer.Equal,
DictionaryEntriesComparer.Equal,
KeyValuePairsComparer.Equal,
StringsComparer.Equal,
StreamsComparer.Equal,
CharsComparer.Equal,
EnumComparer.Equal,
DirectoriesComparer.Equal,
NumericsComparer.Equal,
DateTimeOffsetsComparer.Equal,
TimeSpanToleranceComparer.Equal,
TupleComparer.Equal,
ValueTupleComparer.Equal,
StructuralComparer.Equal,
EquatablesComparer.Equal,
EnumerablesComparer.Equal,
EqualsComparer.Equal
};
private bool _caseInsensitive;
private bool _compareAsCollection;
private bool _compareProperties;
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})]
private List<EqualityAdapter> _externalComparers;
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})]
private List<FailurePoint> _failurePoints;
public bool IgnoreCase {
get {
return _caseInsensitive;
}
set {
_caseInsensitive = value;
}
}
public bool CompareProperties {
get {
return _compareProperties;
}
set {
_compareProperties = value;
}
}
public bool CompareAsCollection {
get {
return _compareAsCollection;
}
set {
_compareAsCollection = value;
}
}
public IList<EqualityAdapter> ExternalComparers => _externalComparers ?? (_externalComparers = new List<EqualityAdapter>());
public IList<FailurePoint> FailurePoints => _failurePoints ?? (_failurePoints = new List<FailurePoint>());
public bool WithSameOffset { get; set; }
[System.Runtime.CompilerServices.NullableContext(2)]
public bool AreEqual(object x, object y, [System.Runtime.CompilerServices.Nullable(1)] ref Tolerance tolerance)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler;
switch (AreEqual(x, y, ref tolerance, new ComparisonState(true))) {
case EqualMethodResult.TypesNotSupported:
defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(49, 2);
defaultInterpolatedStringHandler.AppendLiteral("No comparer found for instances of type '");
defaultInterpolatedStringHandler.AppendFormatted(<AreEqual>g__GetType|25_0(x));
defaultInterpolatedStringHandler.AppendLiteral("' and '");
defaultInterpolatedStringHandler.AppendFormatted(<AreEqual>g__GetType|25_0(y));
defaultInterpolatedStringHandler.AppendLiteral("'");
throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear());
case EqualMethodResult.ToleranceNotSupported:
defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(65, 2);
defaultInterpolatedStringHandler.AppendLiteral("Specified Tolerance not supported for instances of type '");
defaultInterpolatedStringHandler.AppendFormatted(<AreEqual>g__GetType|25_0(x));
defaultInterpolatedStringHandler.AppendLiteral("' and '");
defaultInterpolatedStringHandler.AppendFormatted(<AreEqual>g__GetType|25_0(y));
defaultInterpolatedStringHandler.AppendLiteral("'");
throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear());
case EqualMethodResult.ComparedEqual:
return true;
default:
return false;
}
}
[System.Runtime.CompilerServices.NullableContext(2)]
internal EqualMethodResult AreEqual(object x, object y, [System.Runtime.CompilerServices.Nullable(1)] ref Tolerance tolerance, ComparisonState state)
{
_failurePoints = new List<FailurePoint>();
if (x == null && y == null)
return EqualMethodResult.ComparedEqual;
if (x == null || y == null)
return EqualMethodResult.ComparedNotEqual;
if (x == y)
return EqualMethodResult.ComparedEqual;
if (state.DidCompare(x, y))
return EqualMethodResult.ComparisonPending;
EqualityAdapter externalComparer = GetExternalComparer(x, y);
if (externalComparer != null)
try {
return externalComparer.AreEqual(x, y, ref tolerance) ? EqualMethodResult.ComparedEqual : EqualMethodResult.ComparedNotEqual;
} catch (InvalidOperationException) {
return EqualMethodResult.ToleranceNotSupported;
}
EqualMethod[] comparers = Comparers;
foreach (EqualMethod equalMethod in comparers) {
EqualMethodResult equalMethodResult = equalMethod(x, y, ref tolerance, state, this);
if (equalMethodResult != 0)
return equalMethodResult;
}
if (_compareProperties)
return PropertiesComparer.Equal(x, y, ref tolerance, state, this);
if (tolerance.HasVariance)
return EqualMethodResult.ToleranceNotSupported;
if (!x.Equals(y))
return EqualMethodResult.ComparedNotEqual;
return EqualMethodResult.ComparedEqual;
}
[return: System.Runtime.CompilerServices.Nullable(2)]
private EqualityAdapter GetExternalComparer(object x, object y)
{
if (_externalComparers != null) {
foreach (EqualityAdapter externalComparer in _externalComparers) {
if (externalComparer.CanCompare(x, y))
return externalComparer;
}
}
return null;
}
}
}