EqualConstraint
EqualConstraint is able to compare an actual value with the
expected value provided in its constructor. Two objects are
considered equal if both are null, or if both have the same
value. NUnit has special semantics for some object types.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
namespace NUnit.Framework.Constraints
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class EqualConstraint : Constraint
{
[System.Runtime.CompilerServices.Nullable(2)]
private readonly object _expected;
private Tolerance _tolerance = Tolerance.Default;
private readonly NUnitEqualityComparer _comparer = new NUnitEqualityComparer();
protected internal NUnitEqualityComparer Comparer => _comparer;
public Tolerance Tolerance => _tolerance;
public bool CaseInsensitive => _comparer.IgnoreCase;
public bool IgnoringWhiteSpace => _comparer.IgnoreWhiteSpace;
public bool IgnoringLineEndingFormat => _comparer.IgnoreLineEndingFormat;
public bool ComparingProperties => _comparer.CompareProperties;
public bool ClipStrings { get; set; }
public bool HasFailurePoints => _comparer.HasFailurePoints;
public IList<NUnitEqualityComparer.FailurePoint> FailurePoints => _comparer.FailurePoints;
public EqualConstraint IgnoreCase {
get {
_comparer.IgnoreCase = true;
return this;
}
}
public EqualConstraint IgnoreWhiteSpace {
get {
_comparer.IgnoreWhiteSpace = true;
return this;
}
}
public EqualConstraint IgnoreLineEndingFormat {
get {
_comparer.IgnoreLineEndingFormat = true;
return this;
}
}
public EqualConstraint NoClip {
get {
ClipStrings = false;
return this;
}
}
public EqualConstraint AsCollection {
get {
_comparer.CompareAsCollection = true;
return this;
}
}
public EqualConstraint WithSameOffset {
get {
_comparer.WithSameOffset = true;
return this;
}
}
public EqualConstraint Ulps {
get {
_tolerance = _tolerance.Ulps;
return this;
}
}
public EqualConstraint Percent {
get {
_tolerance = _tolerance.Percent;
return this;
}
}
public EqualConstraint Days {
get {
_tolerance = _tolerance.Days;
return this;
}
}
public EqualConstraint Hours {
get {
_tolerance = _tolerance.Hours;
return this;
}
}
public EqualConstraint Minutes {
get {
_tolerance = _tolerance.Minutes;
return this;
}
}
public EqualConstraint Seconds {
get {
_tolerance = _tolerance.Seconds;
return this;
}
}
public EqualConstraint Milliseconds {
get {
_tolerance = _tolerance.Milliseconds;
return this;
}
}
public EqualConstraint Ticks {
get {
_tolerance = _tolerance.Ticks;
return this;
}
}
public override string Description {
get {
StringBuilder stringBuilder = new StringBuilder(MsgUtils.FormatValue(_expected));
if (_tolerance != null && _tolerance.HasVariance) {
stringBuilder.Append(" +/- ");
stringBuilder.Append(MsgUtils.FormatValue(_tolerance.Amount));
if (_tolerance.Mode != ToleranceMode.Linear) {
stringBuilder.Append(' ');
stringBuilder.Append(_tolerance.Mode.ToString());
}
}
if (_comparer.IgnoreCase)
stringBuilder.Append(", ignoring case");
if (_comparer.IgnoreWhiteSpace)
stringBuilder.Append(", ignoring white-space");
if (_comparer.IgnoreLineEndingFormat)
stringBuilder.Append(", ignoring line ending format");
return stringBuilder.ToString();
}
}
[System.Runtime.CompilerServices.NullableContext(2)]
public EqualConstraint(object expected)
: base(expected)
{
AdjustArgumentIfNeeded(ref expected);
_expected = expected;
ClipStrings = true;
}
internal EqualConstraint WithinConfiguredTolerance(Tolerance tolerance)
{
_tolerance = tolerance;
return this;
}
public EqualConstraint Within(object amount)
{
if (!_tolerance.IsUnsetOrDefault)
throw new InvalidOperationException("Within modifier may appear only once in a constraint expression");
_tolerance = new Tolerance(amount);
return this;
}
public EqualConstraint Using(IComparer comparer)
{
_comparer.ExternalComparers.Add(EqualityAdapter.For(comparer));
return this;
}
public EqualConstraint Using<[System.Runtime.CompilerServices.Nullable(2)] T>(IComparer<T> comparer)
{
((ICollection<EqualityAdapter>)_comparer.ExternalComparers).Add(EqualityAdapter.For(comparer));
return this;
}
public EqualConstraint Using<[System.Runtime.CompilerServices.Nullable(2)] T>(Func<T, T, bool> comparer)
{
((ICollection<EqualityAdapter>)_comparer.ExternalComparers).Add(EqualityAdapter.For(comparer));
return this;
}
public EqualConstraint Using<[System.Runtime.CompilerServices.Nullable(2)] T>(Comparison<T> comparer)
{
((ICollection<EqualityAdapter>)_comparer.ExternalComparers).Add(EqualityAdapter.For(comparer));
return this;
}
public EqualConstraint Using(IEqualityComparer comparer)
{
_comparer.ExternalComparers.Add(EqualityAdapter.For(comparer));
return this;
}
public EqualConstraint Using<[System.Runtime.CompilerServices.Nullable(2)] T>(IEqualityComparer<T> comparer)
{
((ICollection<EqualityAdapter>)_comparer.ExternalComparers).Add(EqualityAdapter.For(comparer));
return this;
}
public EqualConstraint Using<[System.Runtime.CompilerServices.Nullable(2)] TActual, [System.Runtime.CompilerServices.Nullable(2)] TExpected>(Func<TActual, TExpected, bool> comparison)
{
((ICollection<EqualityAdapter>)_comparer.ExternalComparers).Add(EqualityAdapter.For(comparison));
return this;
}
public EqualConstraint UsingPropertiesComparer()
{
_comparer.CompareProperties = true;
_comparer.ComparePropertiesConfiguration = null;
return this;
}
public EqualConstraint UsingPropertiesComparer(Func<PropertiesComparerConfigurationUntyped, PropertiesComparerConfigurationUntyped> configure)
{
_comparer.CompareProperties = true;
_comparer.ComparePropertiesConfiguration = configure(new PropertiesComparerConfigurationUntyped());
return this;
}
public virtual EqualConstraint UsingPropertiesComparer<[System.Runtime.CompilerServices.Nullable(2)] T>(Func<PropertiesComparerConfiguration<T>, PropertiesComparerConfiguration<T>> configure)
{
Comparer.CompareProperties = true;
Comparer.ComparePropertiesConfiguration = configure(new PropertiesComparerConfiguration<T>());
return this;
}
public override ConstraintResult ApplyTo<[System.Runtime.CompilerServices.Nullable(2)] TActual>(TActual actual)
{
if (_comparer.HasFailurePoints)
((ICollection<NUnitEqualityComparer.FailurePoint>)_comparer.FailurePoints).Clear();
AdjustArgumentIfNeeded(ref actual);
return new EqualConstraintResult(this, actual, _comparer.AreEqual(_expected, actual, ref _tolerance));
}
private static void AdjustArgumentIfNeeded<[System.Runtime.CompilerServices.Nullable(2)] T>(ref T arg)
{
if (arg != null) {
Type type = arg.GetType();
Type left = type.IsGenericType ? type.GetGenericTypeDefinition() : null;
if (left == typeof(ArraySegment<>) && type.GetProperty("Array")?.GetValue(arg, null) == null) {
Type elementType = type.GetGenericArguments()[0];
Array array = Array.CreateInstance(elementType, 0);
ConstructorInfo constructor = type.GetConstructor(new Type[1] {
array.GetType()
});
arg = (T)constructor.Invoke(new object[1] {
array
});
}
}
}
}
}